繁体   English   中英

Clojure,尝试调用未绑定的fn

[英]Clojure, Attempting to call unbound fn

我试图使用递归在Clojure中创建阶乘函数

(defn fac[x] (if (= x 1) 1 (* x (fac (- x 1)))))

现在,当我尝试调用该函数时

(fac 5)

我例外

java.lang.IllegalStateException: Attempting to call unbound fn: #'sandbox11355/fac

这是否意味着在使用defn关键字定义函数时无法使用递归?

另外,由于我习惯了命令式/ OOP式的思维方式,我将如何最有效地采用这种功能语法? 以相反的顺序键入所有内容感觉很尴尬。 在过程范式下,思想的连续性直接映射到新的代码行上,从而改变了价值。 使用函数语法,对于操作当前值的每一步,我都必须将新函数包装在表达式周围 ,并且很难跟踪括号和作用域。 我是否应该学会以相反的顺序来考虑过程模型,以流畅地编写功能样式?

我了解没有可变状态和纯函数(较少的bug)的好处,但是很难相信值得失去编写过程代码的便利。 就目前而言,所有这些似乎都过度炒作了无组织的混乱局面,但也许它开始变得有意义了。

以下是有关您对功能和过程编程的关注的一些信息。 它不是特别原始,但是也许它可以帮助您开始思考新事物。

函数式编程不是反向的过程式编程。 这是更高的抽象水平,我们与之交互的大多数事物都可以被视为抽象。 否则,我们将永远无法做任何有用的事情,因为我们会非常关注所处理的每件事的细节。 同样,所有语言的所有代码最终都会变成向CPU发出的一系列指令,这些指令是“命令式”或“过程式”的缩影。 问题变成:“为了解决我的问题,我需要对极低的细节进行多少控制?”

一种将一些数字加在一起的方法,应该非常明确(只是伪代码,希望意图很明确):

int nums[10] = {0,1,2,3,4,5,6,7,8,9};
int i = 0;
int acc = 0;

start_loop:
  if (i >= 10) goto done_loop;

  int num_address = (nums + i);
  int num_value = *num_address;
  acc = acc + num_value;
  i = i + 1;
  goto start_loop;

done_loop:
  return acc;

这很繁琐,但没有汇编代码那么乏味。 为了抽象出一些循环细节,C / java / etc提供了一种称为for循环的控制结构:

int nums[10] = {0,1,2,3,4,5,6,7,8,9};
int acc = 0;

for (int i = 0; i < 10; i++)
  acc += nums[i];

return acc;

当然,当您定期编写命令式代码时,这似乎完全正常。 您需要反复考虑,并详细了解如何在距数组基数偏移的每个位置访问数组。 但是,这也可以认为是乏味的。 我为什么要关心如何访问数组的每个成员的细节? 任何功能语言提供的另一种抽象称为reduce 可以将其视为一种工具,其提供方式类似于为C / java / etc程序员提供的for方式。 它看起来很奇怪,就像for的语法与汇编程序员第一次看到它的样子一样:

(reduce + (range 10))

因此,我们在这里所做的就是将循环的细节抽象出来,以至于我们对实际发生的循环并没有多加考虑。 我们还抽象出了创建一个明确的数字范围的细节,只是说“请给我从0(含)到10(不含)的整数”。 它只是抽象出细节。 结果通常是可以将更多精力放在眼前的问题上。

对于加数或更高层次的思考,一种实用的编程方式通常可以使我们以更少的代码来提高生产力,同时让各种级别的编译器为我们处理混乱的细节。 但是,如果问题的水平很低,那么我们可能希望使用更适合我们问题的语言构造。 关键始终是使用正确的工具完成正确的工作。

当然,这不是一个完美的世界,通常在Clojure中,我们不得不写低级细节来处理位和字节,同步并发代码,循环等等。 但是总体来说,是声明,并说明你想做的事,而不是更加明确如何做到这一点的东西 ,有很多好处。

4clojure问题,给它一个月或两个月才真正有意义,并使您的头脑从变异变量转换为评估表达式。 您很有可能会非常喜欢它,而最糟糕的情况是您会扩大视野。 祝好运并玩得开心点!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM