我正在 Racket 中做一些练习,遇到了一个我似乎无法查询文档的问题。
我想为除数列表生成以下模
柯里式:
(define multlist '[3 5])
(define modfuncs (map (lambda x ;@ make some modulos
(curry modulo x)) multlist))
这会生成一个柯里化(Currying)过程列表,这听起来很有希望,但是当我尝试测试其中一个过程时,出现以下错误:
-> (car modfuncs)
#<procedure:curried>
-> ((car modfuncs) 3)
; modulo: contract violation
; expected: integer?
; given: '(3)
; argument position: 1st
; [,bt for context]
假设这不是一个糟糕的方法,我如何取消引用传递给 curry
/map
的 multlist
值调用以便这些函数能够正确评估?
最佳答案
您实际上做得正确,尽管有一个小错误:
(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 的 rest parameter syntax 的结果。在 lambda 的最后一个参数之前插入一个点使该参数成为一个剩余参数,它成为一个包含传递给函数的所有其他参数的列表。
((lambda (a b . rest) rest) 1 2 3 4 5)
; => '(3 4 5)
然而,这实际上不仅仅是一种特殊的语法。点符号实际上与 Racket 的阅读器如何读取语法中的列表和对有关。上面的参数列表实际上变成了一个由以下 cons 序列组成的“不正确”列表:
(cons 'a (cons 'b 'rest))
没有 rest
参数的相同函数将有一个正确列表作为其参数声明,如下所示:
(cons 'a (cons 'b null))
那么,原始的 x
单独存在又如何呢?嗯,这是一个不正确的列表,没有前面的参数!执行 ( .rest)
没有任何意义,这将是一个语法错误,因为您将尝试创建一个没有 car
元素的对。等价的只是完全删除对语法。
关于functional-programming - 将 curry 映射到参数列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28448661/