2016-07-06 62 views
0

甲函数来添加一个和一个:为什么函数的返回值没有被评估,但宏的返回值是?

(defn one-plus-one [] (list + 1 1))

时调用返回:

(#object[clojure.core$_PLUS_ 0x47fa7bd5 "[email protected]"] 1 1)

相同的功能体包裹在一个宏:

(defmacro one-plus-one [] (list + 1 1))

当被叫回报:

2

为什么Clojure的期望宏返回一个可评估的表情?

编辑

答案the possible duplicate question告诉宏是如何从一个功能有所不同。但是没有回答原因。隐喻地说,我知道一个从高空遗留下来的物体会垂直下落到地面。我的问题是为什么它垂直下降?

+4

[defn和defmacro有什么不同?](http://stackoverflow.com/questions/3667403/what-is-the-difference-between-the-defn-and-defmacro) –

+4

你应该阅读更多关于宏我猜。您可以将宏调用看作是在编译时用宏内容替换自己的代码。因此,对于宏一加一的情况,你可以想象'(一加一)'将'(+ 1 1)'放入你的源代码中,然后和其余的源代码一起评估。 – leetwinski

+1

重新编辑,并从[链接的问题](http://stackoverflow.com/a/3672068/425313)引用函数转换值,宏将代码转换为其他代码。 –

回答

1

就让我们先从一件事解释宏,从而导致学习别人想想宏时是迷茫的时候很多人都知道这么好,他们忘了明确想一想:

------ ----->宏是函数< -------------

它们通常用于获取看起来像代码的东西的列表,并且经常期望返回列表可以实际上作为代码运行。

宏和函数之间的区别并不在于它(从根本上),而在于它的作用。 宏在代码“加载”时运行并且它们返回的值在程序运行时运行。

当你写它作为一个宏它两个步骤:

  • 运行函数产生一个列表
  • 运行一个返回列表,代码生成一个值

当你把它写成一个功能它一步到位:

  • 运行函数产生一个列表

然后停止。

返回值是不同的,因为宏版本需要额外的步骤来运行返回的值作为代码。

代码是数据...数据是代码... yay lisp!

+0

我一直在应用类似的思维过程来理解宏。在REPL过程中,宏位于Read和Eval之间。这就是为什么评估宏的返回值是因为“读取”已经发生。另一方面,函数被评估,并且它的返回值意味着被馈送给读者。我可能是错的。我还在想。 – ardsrk

+0

更多的想法是,函数的返回值打算打印出来,或者执行过程循环返回,并将返回值输入到“读取”步骤。 – ardsrk

+0

@ardsrk是的,你明白了。它会循环回读阶段,如果它仍然是第二阶段的宏,那么它会再次循环返回第三阶段。只是继续前进,直到没有宏。那么最终完全形成的代码实际上会使它成为完成的程序。 –