何时将 lambda 定义与"bare"形式参数一起使用?



我现在正在学习 Guile Scheme,在文档中我突然遇到了以下结构:

((lambda args (display args)) 42)
=> (42)

这让我陷入了循环;在此之前,我一直认为形式参数总是包含在列表中:

((lambda (args) (display args)) 42)
=> 42

我想知道何时使用此变体,以及它与可变参数数量的点表示法有何不同。具体来说,以下两个变体有什么区别:

((lambda args (display args)) 1 2 3)     => (1 2 3)
((lambda (. args) (display args)) 1 2 3) => (1 2 3)

是否有我需要注意的区别——也许是更复杂的例子——是否有任何理由偏爱一个而不是另一个?

不同之处在于此版本接收一个名为 args 的参数,当您确切知道lambda形式预期的实际参数数量时很有用:

(lambda (args) (display args))

此版本接收一个(可能为空的(参数列表,称为 args ,当您期望lambda形式的参数数量可变时很有用:

(lambda args (display args))

以下两个版本之间应该没有区别,但并非所有解释器都会接受第二个版本,因为它缺少点之前的部分(因此应避免(:

(lambda args (display args))
(lambda (. args) (display args))

当您要指定lambda表单具有一个或多个必需参数(点左侧的符号(和零个或多个可选参数的列表(点右侧的单个符号(时,以下版本非常有用:

(lambda (mandadory1 mandatory2 . optional) (display mandatory1))

这让我陷入了循环;在此之前,我一直认为形式参数总是包含在列表中:

请注意,像(a . args)(a b . args)之类的东西也不是真正的列表。 (a . args)是一对,其中car是符号acdr是符号args(a b . args)是一对,其中car是符号acdr是(一对,其中car是符号bcdr是符号args(。有一段时间它看起来有点像一个列表,有ab等等,但由于它不以 null/空列表结尾,所以它不是一个真正的列表。像这样的结构通常被称为不正确的列表。如果你愿意,你可以在这里或其他地方阅读一些关于点线对符号的信息......

对于(. args),我可能会说"这是一对,其中cdr是符号args"。或者也许它会像"一对car在哪里,cdr args"。无论哪种方式,它都没有多大意义,而且,正如Chris Jester-Young所说,它并不是真正有效的Scheme。

所以,像(a b . args)这样的东西只是常规的点对表示法,用于将不为空的东西放在最后cdr中。如果 Scheme 中的形式参数事物可以是那些不正确的列表之一,也可以是一个正确的列表,或者只是一个符号,那么形式参数事物的定义必须是这样的:形式参数事物必须是空值、符号或一对,其中car是一个符号,cdr是一个形式参数事物。

(我认为这是一种很酷的事情,它提供了一种将参数绑定到参数的相当优雅的方式。比如,你看形式参数-thing,如果它是一个符号,你就将参数列表绑定到它,如果它是一个对,你将参数的car绑定到形式参数事物的cdr,并在形式参数事物/参数cdr上重复出现(哦,如果它是空的,你就完成了什么(。这让我觉得比Common Lisp的方式"如果car中的符号是&rest,你在那之后将其余的参数绑定到符号"的方式更漂亮。

最新更新