Существует множество реализаций карри для 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 есть средства для проверки арности функции, и с ее помощью можно реализовать версию функции каррирования, которая знает, когда вызывать исходную функцию.