【问题标题】:What are macros abstractions of in Clojure?Clojure 中的宏抽象是什么?
【发布时间】:2015-04-13 17:57:18
【问题描述】:

我一直在尝试更多地思考抽象在函数式编程中的实际含义。我发现谈论我能理解的语言类型的最好的帖子是4 abstractions。然而,由于我是一个想要成为 Clojure 程序员的人,我想知道宏提供了什么样的抽象。似乎它们与 HOF 一起适合第 2 阶段,但同时它们不仅仅是 HOF。我发现第 3 阶段与表达式问题有关,是 Clojure 中的协议和多方法。所以我的问题是:

在 Lisp 语言中实现宏时,你会说你在抽象什么?

第 3 阶段和第 4 阶段在 Lisp 语言中是什么?

【问题讨论】:

  • 很好的问题,但这更适合CSSE。我会说宏像第 1 阶段一样抽象,但在编译时。函数转换值,宏转换代码,而代码才是真正运行的代码。
  • 我同意@TimothyBaldridge 的回答中我有资格评估的所有部分。我只想强调它们是使用 Lisp 重写 Lisp 源代码的方法。我认为宏不适合这四个抽象列表,因为它们在评估之前就起作用了。但是,宏可能被认为允许在这个意义上进行抽象:您可以使用宏来抽象几个不同函数共有的模式,从宏生成这些函数。这突出了为什么经常可以(并且应该)避免使用宏:HO 函数已经允许类似的东西。

标签: clojure macros


【解决方案1】:

我并不真正将宏视为一种抽象,而更像是一个编译器钩子。

大多数语言都实现了所谓的抽象语法树(或 AST)。这是一种数据结构中程序代码的表示。 Lisp 宏将此 AST 的部分公开为可以通过宏函数转换的数据。但是由于 lisp 程序本身就是数据结构,因此在 lisp 程序中的宏往往比在 Rust 或 Scala 中更简洁。

因此可以说宏只是语言语义的抽象……但我不知道我是否同意这一点。可以说宏是 lisp 编译器的扩展,但也不完全正确。

事实证明,宏非常有限。他们只能看到正在编译的代码的一小部分。换句话说,宏不能向上看树,只能向下看。此外,虽然可以对 AST 中的子节点进行深度检查(称为深度行走宏),但这些宏往往很复杂且容易出错(只需查看 core.async 的内容或 midje 的内容即可了解复杂的这些可以得到)。所以我不愿称它们为抽象,也许它们是,也许它们只是非常有限的抽象。

所以我认为宏是功能更强大的 Fexprs (http://en.wikipedia.org/wiki/Fexpr) 和 LLVM 等项目中更完整的编译器代码转换之间的奇怪组合。它们提供了一种非常有限的受控方式来在编译时转换代码,仅此而已。

最后,这一切都归结为“代码就是数据就是代码”的 lisp 口头禅。如果您的代码是数据,那么在编译时提供转换它的方法是有意义的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    • 2011-06-13
    • 2011-10-25
    • 2020-03-05
    • 1970-01-01
    相关资源
    最近更新 更多