Определение собственного макроса для проверки условия - Lisp
Формулировка задачи:
- (OUR-IF test :THEN exp1 exp2… :ELSE exp3 exp4 …)
- > (our-if (> 3 1) :then ‘ok)
- OK
- > (our-if (< 5 3) :else ‘ok)
- OK
- > (our-if (> 3 1) :else ‘oops)
- NIL
- > (our-if (> 3 1) :then)
- NIL
- > (our-if (> 3 1) :else ‘oops :then ‘ok)
- ok
- > (our-if (> 3 1) :then ‘ok :else ‘oops)
- ok
- (defmacro our-if (test &rest body)
- (let* ((bt (position :then body))
- (et (position :else body))
- (th (cdr (member :then body)))
- (el (cdr (member :else body))))
- `(cond
- (,test, nil ,@th)
- (t ,@el))))
Решение задачи: «Определение собственного макроса для проверки условия»
- (defmacro our-if (&body body)
- (destructuring-bind (test-form &optional body-clause)
- (split-sequence :then body)
- (when body-clause
- (destructuring-bind (then-form &optional else-form)
- (split-sequence :else body-clause)
- `(if (progn ,@test-form)
- (progn ,@then-form)
- (progn ,@else-form))))))
- (macroexpand '(our-if 1))
- ;; NIL
- ;; T
- (macroexpand '(our-if 1 :then (foo) (bar)))
- ;; (IF (PROGN 1)
- ;; (PROGN (FOO) (BAR))
- ;; (PROGN))
- ;; T
- (macroexpand '(our-if 1 :then (foo) (bar) :else (baz)))
- ;; (IF (PROGN 1)
- ;; (PROGN (FOO) (BAR))
- ;; (PROGN (BAZ)))
- ;; T
Объяснение кода листинга программы
В этом коде определён макрос с именем our-if
. Этот макрос принимает произвольное количество аргументов, которые могут быть либо одним выражением, либо последовательностью выражений, заключённых в begin
и разделённых запятыми. Аргументы, которые являются последовательностью выражений, разделённых запятыми, заключены в split-sequence
. Это выражение либо помещается в then-form
, либо в else-form
в зависимости от того, есть ли у аргумента заголовок :then
.
В этом макросе используется вспомогательный макрос split-sequence
, который принимает два аргумента: последовательность для разбиения и заголовок, который определяет, где поместить результат разбиения. Если заголовок :then
, то результат помещается в then-form
, если :else
, то в else-form
.
Синтаксис этого макроса напоминает синтаксис встроенного макроса if
, за исключением того, что вместо then-form
и else-form
используется test-form
, then-clause
и else-clause
.
Когда макрос our-if
вызывается с аргументом :then
и без :else
, результат будет nil
, потому что он ожидает два аргумента после :then
.
Когда макрос our-if
вызывается с аргументами :then
и :else
, и без аргументов, результат будет nil
, потому что он ожидает по крайней мере один аргумент после каждого из ключевых слов :then
и :else
.
Когда макрос our-if
вызывается с аргументами :then
и :else
, и с аргументами после каждого из ключевых слов :then
и :else
, результат будет nil
, потому что он ожидает еще одного аргумента после каждого из ключевых слов :then
и :else
.
Когда макрос our-if
вызывается с аргументами :then
и :else
, и с аргументами после каждого из ключевых слов :then
и :else
, и без аргументов, результат будет nil
, потому что он ожидает по крайней мере одного аргумента после каждого из ключевых слов :then
и :else
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д