2015-02-11 3 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's 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. Эквивалент просто полностью исключает синтаксис пары.