【问题标题】:Writing lambda expressions in common lisp用 common lisp 编写 lambda 表达式
【发布时间】:2012-10-24 04:43:44
【问题描述】:

我目前正在阅读 Paul Graham 的 ANSI Common Lisp,并且我有一个关于编写 lambda 表达式的问题。

我们是否需要在 lambda 表达式前面加上 #'?。如果我在 REPL 中写这样的东西,它会正常工作

> ((lambda (x) (+ x 1)) 1)
  2

这个也可以

> (mapcar (lambda (x) (+ x x)) '(1 2 3 4))
  (2 4 6 8)

我知道#' 表示一个函数。所以我的问题是,这是某种约定还是推荐的做法?如果我不在 lambdas 前面加上 #',会不会出什么问题,它是否依赖于实现?

【问题讨论】:

标签: common-lisp lambda clisp


【解决方案1】:

LAMBDA 表达式

(lambda ...) 仅在某些地方被视为 lambda 表达式,例如 function 形式或作为函数调用的头部。不计算 Lambda 表达式。

(function              ; special operator FUNCTION
  (lambda () 'foobar)) ; <- this is a lambda expression


(                    ; a function call
 (lambda (foo) foo)  ; <- this is a lambda expression
 'bar                ; argument
)

但是这里(lambda ...)是一个宏形式而不是一个lambda表达式:

(funcall             ; calling a function via funcall
 (lambda (foo) foo)  ; this is not a lambda expressions, but the macro lambda
                     ;  as all arguments to FUNCALL it will be
                     ;    macro expanded and evaluated
                     ;  it expands to (function (lambda (foo) foo))
 'bar)               ; argument

LAMBDA 宏

LAMBDA 是一个宏。它将(lambda ...) 扩展为(function (lambda ...)),相当于#'(lambda ...))

CL-USER > (macroexpand '(lambda (foo) foo))
(FUNCTION (LAMBDA (FOO) FOO))

宏为您节省了一些写作/阅读时间,仅此而已。在 Common Lisp (CLtL1) 的第一个版本中,没有 LAMBDA 宏。它是后来添加的,现在是 ANSI Common Lisp 的一部分

FUNCTION 特殊运算符

FUNCTION 是一个特殊的运算符。它需要一个函数名或 lambda 表达式。因此,不会评估名称或 lambda 表达式。事实上 lambda 表达式 根本无法计算。在FUNCTION 内部,lambda 表达式 不是 宏形式,因此将不会 再次展开。 FUNCTION 的目的是返回由名称或 lambda 表达式 表示的相应函数对象。它将函数对象作为值返回。有了这个特殊的操作符,我们可以从全局函数和词法函数中访问函数对象。

FUNCTION 运算符在 Common Lisp 中是必需的,因为它为值、函数和其他一些东西提供了单独的命名空间。它就像一个所谓的 Lisp-2 甚至 Lisp-n,有两个或多个命名空间。

函数形式中函数位置的 Lambda 表达式

((lambda (foo) foo) 10) 由 Common Lisp 的内置语法支持。见Lambda Forms

令人困惑

这都是合乎逻辑的,但令人困惑。不要担心你并不孤单,但实际上这没什么大不了的。

【讨论】:

  • 谢谢,我仍然不明白为什么人们在 lambda 表达式之前明确写 #'。
  • 风格问题。有些人喜欢它,有些人不喜欢。我更喜欢它,因为它可以轻松识别用作值的实际函数。它还可以更轻松地替换为 fletlabels 函数。除了 lambda,它还可以查找函数的定义。如果您不知道实现是否预先强制function designator,这可能是可取的,例如(mapcar 'frob my-list) 可以查找 frobsymbol-functionmy-list 中的元素一样多次。
  • Doug Hoyte 提供了一个不使用 #' 语法的论据。 Rainer 在这里暗示了这一点;事实上 ((lambda (foo) 是内置语法,并且有一个 (lambda 宏),这意味着您可以在使用读取宏时使用这种语法的二元性做一些有趣的事情。查看 Hoyte 的 cl-ppcre read-macro 扩展例如:letoverlambda.com/index.cl/guest/chap4.html#sec_4
  • 关于claytonstanleys 的评论:快速警告,'Let Over Lambda' 包含一些宏技术,有些人认为这些技术在风格和可维护性方面存在问题。我喜欢这本书,并衷心推荐购买它,但请注意其中蕴含着深厚的魔力,人们应该认真考虑将来会查看您的代码的最终用户/编码员。
猜你喜欢
  • 2015-12-20
  • 1970-01-01
  • 1970-01-01
  • 2021-08-11
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
相关资源
最近更新 更多