将咖喱映射到参数列表
问题描述:
我在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]
假设这是不是做这个可怕的方式,我该如何解除引用的multlist
传递给curry
/map
调用的值,以便这些功能将evalua正确吗?
答
你实际上这样做正确,尽管有一个微小的失误:
(lambda x (curry modulo x))
这不会做你认为它。你实际上要的是这样的:
(lambda (x) (curry modulo x))
看到区别?在前者中,x
不在参数列表中,因此它实际上会传递一个所有传递给函数的参数列表,而不是一个参数。
您可以看到此行为为自己与下面的程序:
((lambda x x) 1 2 3)
; => '(1 2 3)
因此,您curry
功能是接收一个数字的列表x
,而不是一个实际的整数。
所以也许更令人满意的答案是:为什么球拍做到这一点?那实际上这是Racket/Scheme的rest parameter syntax的结果。在拉姆达的最后一个参数之前插入一个点使得该参数为其余参数,该参数成为保存传递给该函数的所有附加参数的列表。
((lambda (a b . rest) rest) 1 2 3 4 5)
; => '(3 4 5)
但是,这实际上并不仅仅是一种特殊的语法。点符号实际上与Racket的读者如何在语法中读取列表和对相关。以上参数列表实际上变成以下缺点序列组成的“不正当”的文章:
(cons 'a (cons 'b 'rest))
没有rest
参数相同的功能将有一个适当列表作为它的参数声明,这将是这样的相反:
(cons 'a (cons 'b null))
那么,那么原来的x
刚刚独立呢?那么,这是一个不合适的名单,没有先前的论点!做(. rest)
没有任何意义 - 这将是一个语法错误 - 因为你会试图创建一个没有car
元素的对。等价物只是完全放弃对语法。