Определение собственного макроса для проверки условия - 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
.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д