Scheme 球拍/方案-(定义((函数名arg1)arg2)(主体…)-符号

Scheme 球拍/方案-(定义((函数名arg1)arg2)(主体…)-符号,scheme,racket,Scheme,Racket,这个符号的名称是什么/它代表什么 (define ((function-name arg1) arg2) (body ...)) 我理解,在Racket/Scheme中,您可以通过以下两种方式定义函数: (define (function-name arg1 arg2 ...) (body ...)) (define function-name (lambda (arg1 ...) (body ...)) 然而,我最近在Chris Hanson和Gerald Jay Sussman的《软件

这个符号的名称是什么/它代表什么

(define ((function-name arg1) arg2) (body ...))
我理解,在Racket/Scheme中,您可以通过以下两种方式定义函数:

(define (function-name arg1 arg2 ...) (body ...))

(define function-name (lambda (arg1 ...) (body ...))
然而,我最近在Chris Hanson和Gerald Jay Sussman的《软件灵活性设计》中遇到了这种符号:

(define ((function-name arg1) arg2) (body ...))
我注意到这个符号在Scheme(这本书就是用它写的)和Racket中也起作用


有人知道define语句参数中函数应用程序的此符号的名称吗?/它可能代表什么?

这肯定是不寻常的,我从未在任何地方看到过它的明确文档,但它至少在一些方案实现中起作用(Chicken、Racket,无论您尝试接受什么方案,Guile都不接受)

(define ((function-name arg1) arg2) (body ...))
R7RS的措辞提供了一些见解:

(定义(〈变量〉〈形式〉)〈主体〉)

〈形式〉
是零个或多个变量的序列,或者是一个或多个变量的序列,后跟一个空格分隔的句点和另一个变量(如lambda表达式)。此表单相当于
(定义〈变量〉(lambda(〈formals〉)〈body〉)

因此:

(定义((示例a)b)(printf“~a~%~a~%”ab))
可以认为相当于

(定义(示例a)(lambda(b)(printf“~a~%~a~%”ab)))
这反过来相当于

(定义示例(lambda(a)(lambda(b)(printf“~a~%%~a~%%”ab)))

接受这种符号的方案可能在某种程度上在内部进行类似的转换,作为实现函数的一部分。当使用第一种形式定义鸡肉时,这与
示例
在鸡肉上的行为相匹配。

这是一种扩展,而不是标准方案的一部分。这个扩展已经在MIT/GNU方案中使用了相当长的一段时间,其他一些实现也采用了它

R7RS规范未显示与OP发布的示例定义匹配的表单。最接近的匹配是5.3。变量定义

  • (定义())

    是零个或多个变量的序列,或者是一个或多个变量后跟空格分隔的句点和另一个变量的序列(如lambda表达式中)
有关的定义是:

(define ((function-name arg1) arg2) (body ...))
在这里,
(函数名arg1)
必须被视为一个变量,以便与标准中的描述相匹配;但它不是一个变量,甚至不是一个标识符

3.1。变量、语法关键字和区域

命名位置的标识符称为变量,并被称为绑定到该位置

值得指出的是,汉森和苏斯曼的书附录B简要讨论了这种结构:

在MIT/GNU方案中,我们可以递归地使用sugar来编写:

(define ((compose f g) x)
  (f (g x)))
现在,在第页。麻省理工学院/GNU方案参考手册(11.1)中的第17部分显示:

(define (name1 name2 ...)
  expression
  expression ...)
相当于:

(define name1
  (named-lambda (name1 name2 ...)
    expression
    expression ...))
请注意,MIT/GNU手册中显示的语法为
lambda

lambda形式表达式。。。[扩展标准特别表格]

这里,formals被描述为“形式参数列表”,但请注意,没有使用术语变量。术语变量在手册的其他地方使用,例如在
let
表单的说明中

名为lambda的
特殊形式如下所述:

命名lambda形式表达式。。。[特别表格]
命名的lambda特殊形式类似于lambda,只是形式中的第一个“必需参数”不是参数,而是结果过程的名称;因此,Formal必须至少有一个必需的参数。此名称没有语义含义,但包含在过程的外部表示中,因此对调试非常有用。在MIT/GNU方案中,lambda被实现为命名lambda,其特殊名称表示“未命名”

因此,定义
(define((函数名arg1)arg2)(body…)
可以重写为:

(define (function-name arg1)
  (named-lambda ((function-name arg1) arg2) (body ...)))
根据手册提供的上述转换规则,由于形式参数列表在MIT/GNU方案中已扩展,因此它不限于仅包含变量

最后一个结果可以使用相同的规则再次展开(递归):

(define function-name
  (named-lambda (function-name arg1)
    (named-lambda ((function-name arg1) arg2)
      (body ...))))
由于
命名lambda
类似于
lambda
,即不同之处在于有一些额外的元数据与之关联,但语义相同,因此我们可以编写语义等价物:

(define function-name
  (lambda (arg1)
    (lambda (arg2)
      (body ...))))
这只是高阶过程的定义。因此,所讨论的符号只是语法上的糖分,以便于高阶过程的定义。请注意,它旨在为其他方案实现提供此功能,并将其称为“高阶
define
form”,以及“定义
define
form的“currying”变体”

回到《软件灵活性设计》附录B中的示例程序,可以看出,可以演示如何使用这种语法糖来灵活地表达函数组合的思想

(define ((compose f g) x)
  (f (g x)))
这里,
compose
是一个接受两个参数的过程,
f
g
,它返回一个接受一个参数的过程
x

1(用户)=>(定义我的合成(合成方形立方体))
;价值观:我的作文
1(用户)=>(我的作文2)
;数值:64
在Racket中,它被称为“Curried函数速记”。看见