Если посмотреть на другие вызовы, условие условия для 'mrg должно быть
((equal 'mrg (car A)) (let ((A A)) (funcall (car A) (my_eval (cadr A)) (my_eval (caddr A)))))
A
должно быть списком, так как он не прошел первый cond
-класс (atom A)
.
Поскольку mrg
требует в этой реализации два аргумента, как и в этом eval, встроенные функции
`cons`
`list`
`equal`
`*`
`/`
`+`
`-`
`=`
также делают после копирования списка A
в локальный символ A
(часть (let ((A A)) ...)
), funcall
применяется к первому элементу ist A
(то есть mrg
), а затем два следующих элемента в списке A
задаются в качестве аргументов для mrg
funcall
-call:
- , а именно
(cadr A)
(что является синонимом (second A)
) и (caddr A)
(что является синонимом (third A)
).
Поскольку каждый из аргументов может быть атомом или другим вызовом функции или специальной формой, вы должны обернуть вокруг него вызов my_eval
и оценить каждый из аргументов.
- Это, кстати, то, что всегда происходит, если вы вызываете функции Lisp - каждый аргумент (который является выражением) полностью вычисляется перед обработкой результата до вызова основной функции.
(Напротив, в вызовах макросов аргументы не оцениваются по умолчанию, как в вызовах функций. Вместо этого в теле функции вы имеете полный контроль над тем, когда каждый из аргументов будет оцениваться или обрабатываться как символ).
В своем комментарии к ответу @ blihp вы дважды цитировали A ('A
) в форме let
, и это препятствует тому, чтобы A принимали за список, которым он фактически соответствует.
Другая проблема, которую я вижу, заключается в том, что ваш my_eval
не ищет quote
, и я также не уверен, может ли ваша реализация my_eval
, которая является очень элементарной, правильно обрабатывать '
.Таким образом, в тестовом вызове mrg
я рекомендую использовать (list 1 3 4 2 4 ...)
вместо '(1 3 4 2 4 ...)
для предотвращения дальнейших осложнений.