你可以用 Lisp 宏做什么,而一流的函数却做不到?

2022-01-11 00:00:00 python macros lisp

问题描述

我想我了解 Lisp 宏及其在编译阶段的作用.

I think I understand Lisp macros and their role in the compilation phase.

但是在 Python 中,你可以将一个函数传递给另一个函数

But in Python, you can pass a function into another function

def f(filename, g):
  try:                                
     fh = open(filename, "rb") 
     g(fh)
  finally:
     close(fh) 

所以,我们在这里得到惰性求值.我可以用宏而不是函数作为第一类对象来做什么?

So, we get lazy evaluation here. What can I do with macros and not with functions as first class objects?


解决方案

首先 Lisp 也有一流的函数,所以你不妨问:既然我已经有了一流的功能,为什么还要在 Lisp 中使用宏职能".答案是一流的函数不允许您使用语法.

First of all Lisp has first-class functions too, so you could as well ask: "Why do I need macros in Lisp if I already have first-class functions". The answer to that is that first-class functions don't allow you to play with syntax.

在外观层面上,一流的函数允许您编写 f(filename, some_function)f(filename, lambda fh: fh.whatever(x)),但不是 f(filename, fh, fh.whatever(x)).虽然可以说这是一件好事,因为在最后一种情况下,fh 突然来自哪里就不太清楚了.

On a cosmetic level, first-class functions allow you to write f(filename, some_function) or f(filename, lambda fh: fh.whatever(x)), but not f(filename, fh, fh.whatever(x)). Though arguably that's a good thing because in that last case it is a lot less clear where fh suddenly comes from.

更重要的是,函数只能包含有效的代码.所以你不能写一个高阶函数 reverse_function 接受一个函数作为参数并反向"执行它,所以 reverse_function(lambda: "hello world" print) 将执行 print "hello world".使用宏可以做到这一点.当然,这个特定的例子非常愚蠢,但这种能力在嵌入特定领域的语言时非常有用.

More importantly functions can only contain code that is valid. So you can't write a higher-order function reverse_function that takes a function as an argument and executes it "in reverse", so that reverse_function(lambda: "hello world" print) would execute print "hello world". With a macro you can do this. Of course this particular example is quite silly, but this ability is enormously useful when embedding domain specific languages.

例如,您无法在 python 中实现 common lisp 的 loop 构造.见鬼,如果它不是真正内置的,你甚至无法在 python 中实现 python 的 for ... in 构造——至少不是用那种语法.当然你可以实现类似 for(collection, function) 的东西,但这样就不太漂亮了.

For example you couldn't implement common lisp's loop construct in python. Hell, you couldn't even implement python's for ... in construct in python if it wasn't really built-in - at least not with that syntax. Sure you could implement something like for(collection, function), but that's a lot less pretty.

相关文章