我在Racket做了一些练习,遇到了一个我无法查询文档的问题。
我希望为除数列表生成以下modulo
的curries:
(define multlist '[3 5])
(define modfuncs (map (lambda x ;@ make some modulos
(curry modulo x)) multlist))
这会生成一个curried程序列表,听起来很有希望,但是当我尝试测试其中一个时,我收到以下错误:
-> (car modfuncs)
#<procedure:curried>
-> ((car modfuncs) 3)
; modulo: contract violation
; expected: integer?
; given: '(3)
; argument position: 1st
; [,bt for context]
假设这不是一种可怕的方法,我如何取消引用传递给multlist
/ curry
调用的map
的值,以便这些函数正确评估?
答案 0 :(得分:5)
你实际上是这样做的,尽管有一个小小的错误:
(lambda x (curry modulo x))
这并不是你认为它做的。您实际想要的是:
(lambda (x) (curry modulo x))
看到区别?在前者中,x
不在参数列表中,因此它实际上将传递一个传递给函数的所有参数的列表,而不是单个参数。
您可以使用以下简单程序自行查看此行为:
((lambda x x) 1 2 3)
; => '(1 2 3)
因此,您的curry
函数正在接收x
的一个数字列表,而不是实际的整数。
所以也许更令人满意的答案是:为什么Racket会这样做?嗯,这实际上是Racket / Scheme&#39; rest parameter syntax的结果。在lambda的最后一个参数之前插入一个点会使该参数成为 rest参数,该参数将成为一个包含传递给函数的所有其他参数的列表。
((lambda (a b . rest) rest) 1 2 3 4 5)
; => '(3 4 5)
但是,这实际上只是一种特殊的语法。点符号实际上与Racket读者如何读取语法中的列表和对有关。上面的参数列表实际上变成了&#34;不正确的&#34;列表由以下cons序列组成:
(cons 'a (cons 'b 'rest))
没有rest
参数的相同函数将有一个正确的列表作为其参数声明,它将如下所示:
(cons 'a (cons 'b null))
那么,原来x
独自站立怎么样?那么,这是一个没有先前争论的不正确的列表!执行( . rest)
不会有任何意义 - 这将是语法错误 - 因为您正在尝试创建一个没有car
元素的对。相当于完全放弃了对语法。