2015-02-11 121 views
2

我在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正确吗?

回答

5

你实际上这样做正确,尽管有一个微小的失误:

(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元素的对。等价物只是完全放弃对语法。