将 curry 映射到参数列表
Mapping curry to a list of parameters
我正在用 Racket 做一些练习,运行 遇到了一个我似乎无法查询文档的问题。
我想为除数列表生成 modulo
的以下咖喱:
(define multlist '[3 5])
(define modfuncs (map (lambda x ;@ make some modulos
(curry modulo x)) multlist))
这会生成一个柯里化过程列表,听起来很有希望,但是当我尝试测试其中一个时,出现以下错误:
-> (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 的 reader 如何读取语法中的列表和对有关。上面的参数列表实际上变成了一个"improper"列表,由下面的cons序列组成:
(cons 'a (cons 'b 'rest))
没有 rest
参数的相同函数将有一个 适当的 列表作为其参数声明,它看起来像这样:
(cons 'a (cons 'b null))
那么,原来的x
一个人呢?好吧,这是一个不正确的列表,没有前面的参数!执行 ( . rest)
没有任何意义——这将是一个语法错误——因为你试图创建一个没有 car
元素的对。等价于完全删除对语法。
我正在用 Racket 做一些练习,运行 遇到了一个我似乎无法查询文档的问题。
我想为除数列表生成 modulo
的以下咖喱:
(define multlist '[3 5])
(define modfuncs (map (lambda x ;@ make some modulos
(curry modulo x)) multlist))
这会生成一个柯里化过程列表,听起来很有希望,但是当我尝试测试其中一个时,出现以下错误:
-> (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 的 reader 如何读取语法中的列表和对有关。上面的参数列表实际上变成了一个"improper"列表,由下面的cons序列组成:
(cons 'a (cons 'b 'rest))
没有 rest
参数的相同函数将有一个 适当的 列表作为其参数声明,它看起来像这样:
(cons 'a (cons 'b null))
那么,原来的x
一个人呢?好吧,这是一个不正确的列表,没有前面的参数!执行 ( . rest)
没有任何意义——这将是一个语法错误——因为你试图创建一个没有 car
元素的对。等价于完全删除对语法。