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

Другие вопросы по тегам