Неявное каррирование в Scheme с синтаксическими правилами?
У Джеффри Менье есть неявный макрос Curry, который использует defmacro. Мне было интересно, если кто-то когда-либо писал это с синтаксическими правилами?
1 ответ
Существует несколько реализаций карри для Scheme - ни одна из них не может быть столь же элегантной, как Haskell, поскольку там всегда есть унарные функции, поэтому все может быть каррировано. (Но это, конечно, может быть реализовано в достаточно мощной схеме, такой как Racket.)
Что касается макроса, который вы выкопали - он довольно плохой: он не только использует негигиеничный макрос, но и вызывает eval
явно, и опирается на реализацию сред и т. д. Но это легко сделать с помощью простого syntax-rules
макро. AFAICT, это то, что он реализует:
(define-syntax-rule (clambda (x ... . r) b ...)
(let ([len (length '(x ...))] [real (lambda (x ... . r) b ...)])
(let loop ([argss '()] [n 0])
(lambda args
(let ([n (+ n (length args))] [argss (cons args argss)])
(if (>= n len)
(apply real (apply append (reverse argss)))
(loop argss n)))))))
Но здесь есть важное замечание. На странице, на которую вы ссылаетесь, говорится, что проблема версии функции заключается в том, что она является явной, но она также имеет важное преимущество: при реализации макроса вы должны определить функцию, используя clambda
тогда как функциональная версия может использоваться с любой встроенной функцией. Во многих реализациях Scheme есть средства для проверки арности функции, и с ее помощью можно реализовать версию функции каррирования, которая знает, когда вызывать исходную функцию.