Clojure宏与C宏有何不同?
我对Clojure不熟悉。我是几个月前开始的。 我正在努力学习宏 最初,我对Clojure中宏和高阶函数之间的区别感到困惑,因为高阶函数可以接受lambdas并根据任何条件和过滤器执行其中一个函数多少次 所以我在StackOverflow上发布了一个简单的例子。 我从答案中消除了疑虑 这就是我所理解的Clojure宏与C宏有何不同?,clojure,Clojure,我对Clojure不熟悉。我是几个月前开始的。 我正在努力学习宏 最初,我对Clojure中宏和高阶函数之间的区别感到困惑,因为高阶函数可以接受lambdas并根据任何条件和过滤器执行其中一个函数多少次 所以我在StackOverflow上发布了一个简单的例子。 我从答案中消除了疑虑 这就是我所理解的 宏不会计算所有参数,不像函数那样计算主体 宏可以选择计算什么和不计算什么,以及如何使用引号、取消引号和拼接语法将一段代码转换为另一段代码 然后对宏生成的最终代码进行求值 所以我的问题是,它与C
- 宏不会计算所有参数,不像函数那样计算主体
- 宏可以选择计算什么和不计算什么,以及如何使用引号、取消引号和拼接语法将一段代码转换为另一段代码
- 然后对宏生成的最终代码进行求值
Lisp/Clojure宏为开发人员提供了什么样的能力,而C宏完全缺乏这种能力,并且经常被广泛使用。C宏允许纯文本替换,并且非常愚蠢(就可以执行的操作而言)。此外,如果它允许更复杂的表达式,那么使用它会很麻烦,因为您正在操作普通字符串
由于Clojure和Lisps通常使用S表达式(只是简单的链表),并允许在宏展开时使用完整的语言,因此您可以构建更复杂、更有用的表达式。一些显著的区别:
- Clojure宏在Lisp数据结构上运行,而C宏在文本上运行。此功能是Lisp的结果(即Lisp源代码表示为Lisp数据结构)。同象性对于一个宏观系统的有效性来说并不是绝对必要的,但它确实使它更加方便和自然李>
- 您可以在运行时执行Clojure宏,也可以在编译时执行(例如,使用
)eval
- Clojure宏是用Clojure本身编写的。与C预处理器宏不同,C预处理器宏有自己独立的迷你语言。在编写更复杂的宏时,这是一个很大的优势:您不必在心理上在不同的语言之间切换(当然,您仍然需要在心理上区分在处理宏时要执行的代码与要作为宏输出生成的代码)
- Clojure宏是图灵完成的,您可以在其中执行任意代码生成。对于标准的C预处理器宏,情况并非如此,因为它们在表达复杂代码生成的能力方面有一定的限制编辑:感谢Jeremy提供了一些有趣的黑客链接,通过这些链接,可以强制C预处理器以完全的方式运行。尽管如此,总的观点仍然站得住脚:这些都不是编写通用代码的真正实用的方法
可以说,宏仍然是Lisps的显著“杀手特性”。关于这个主题的额外解释,值得一读Paul Graham的文章“C宏纯粹是文本重写宏。除了它们的来源之外,它们没有什么可怕的C语言——你可以在任何文本上使用C语言的预处理器。因此,使用C预处理器可以很容易地生成非C表单,而且您经常需要跳转来完成C本身所做的相当琐碎的事情。由于这个原因,C宏充满了错误
是使用与常规Clojure函数不同的规则集执行的Clojure代码。它们不是接收经过计算的参数并返回结果,而是接收未经计算的表单并返回一个表单,该表单最终可能会在正常执行过程中进行计算。实际上,您可以拥有一个完整的宏系统,而不必使用同象性。用于表示代码的数据结构的形状比Lisp数据结构更复杂。请参阅示例。另一件事是列出的属性的结果,但应单独列出,即使用Clojure宏可以轻松创建新的控件结构(条件窗体、循环、带-…窗体等)然后可以使用普通的CuljulySythal.@ JeleMyW.Selman,你可以考虑C宏图灵完成,但是仍然不可能与它们进行任意的转换(即使你做了多少遍你想要的),我认为这是更重要的一点。例如,您不能编写宏
M
,例如M(f(x))
扩展到f(x,y)
或g(x)
@sepp2k-Aye,但人们常常像高杠一样保持图灵完整性。有大量非常丑陋的低级语言有意或半无意地表现出图灵完整性。作为一种实用的通用编程语言是完全不同的