将咖喱映射到参数列表

时间:2015-02-11 07:22:01

标签: functional-programming scheme racket currying

我在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的值,以便这些函数正确评估?

1 个答案:

答案 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元素的对。相当于完全放弃了对语法。