Принудительная оценка рекурсивного вызова в сопоставлении с образцом - PullRequest
0 голосов
/ 26 февраля 2011

Я использую match-lambda для переписывания определенных функций в терминах более простых. Вот пример, который принимает строки, представляющие входной код для вызовов let *, и возвращает их в виде строк, преобразованных во вложенные унарные let:

(define let*→nested-unary-lets
  (match-lambda
   (`(let* (()) ,<exprs>)
   `(let () ,<exprs>))
   (`(let* ((,<var> ,<val>)) ,<exprs>)
   `(let ((,<var> ,<val>)) (let () ,<exprs>)))
   (`(let* ((,<var> ,<val>) . ,<clauses>) ,<exprs>)
   `(let ((,<var> ,<val>)) (let*→nested-unary-lets '(let* (,@<clauses>) ,<exprs>))))))

Вот пример вызова let * → nested-unary-let:

(let*→nested-unary-lets '(let* ((a 1) (b (+ a 1)) (c (+ a b))) (displayln c)))
'(let ((a 1))
   (let*→nested-unary-lets
    '(let* ((b (+ a 1)) (c (+ a b)))
       (displayln c))))

Мне было интересно, есть ли какой-нибудь способ заставить вычисление рекурсивного вызова позволить * → nested-unary-let, чтобы выходная строка содержала только вложенные let и не требовала дальнейшей оценки.

Спасибо.

1 Ответ

1 голос
/ 26 февраля 2011

Вы уже используете квазицитирование для вывода своего ответа в рекурсивном случае, поэтому просто добавьте запятую (,) перед рекурсивным вызовом к let*->nested-unary-lets (как те, что до <var> и <val>), чтобыоценивается сразу., в квазицитатах может склеиваться в результате любого выражения, а не только переменных.Строка:

`(let ((,<var> ,<val>)) (let*→nested-unary-lets '(let* (,@<clauses>) ,<exprs>)))

также имеет некоторые другие проблемы: чтобы ,@ работал, ' перед внутренним let* должен быть `.Вот версия, которую я предлагаю:

`(let ((,<var> ,<val>)) ,(let*→nested-unary-lets `(let* ,<clauses> . ,<exprs>)))

Это требует, чтобы совпадение для <exprs> было изменено на . ,<exprs>, чтобы разрешить более одного.

...