Определение собственного макроса для проверки условия - Lisp

Узнай цену своей работы

Формулировка задачи:

Здравствуйте. Помогите пожалуйста с написанием макроса на LISP. Определить макрос our-if, который имеет следующую форму
Листинг программы
  1. (OUR-IF test :THEN exp1 exp2 :ELSE exp3 exp4 …)
Макрос производит следующие действия:
Листинг программы
  1. > (our-if (> 3 1) :then ok)
  2. OK
  3. > (our-if (< 5 3) :else ok)
  4. OK
  5. > (our-if (> 3 1) :else oops)
  6. NIL
  7. > (our-if (> 3 1) :then)
  8. NIL
  9. > (our-if (> 3 1) :else oops :then ok)
  10. ok
  11. > (our-if (> 3 1) :then ok :else oops)
  12. ok
Дело в том, что я видела похожее задание с решением на этом форуме, однако оно не подходит для данных действий) Я попыталась переделать что то сама:
Листинг программы
  1. (defmacro our-if (test &rest body)
  2. (let* ((bt (position :then body))
  3. (et (position :else body))
  4. (th (cdr (member :then body)))
  5. (el (cdr (member :else body))))
  6. `(cond
  7. (,test, nil ,@th)
  8. (t ,@el))))
И оно даже выдает то что нужно почти для всех случаев, кроме последнего, но я точно знаю что данный макрос не верен и работает некорректно. А как переделать, ума не приложу. буду благодарна за помощь!)

Решение задачи: «Определение собственного макроса для проверки условия»

textual
Листинг программы
  1. (defmacro our-if (&body body)
  2.   (destructuring-bind (test-form &optional body-clause)
  3.       (split-sequence :then body)
  4.     (when body-clause
  5.       (destructuring-bind (then-form &optional else-form)
  6.           (split-sequence :else body-clause)
  7.         `(if (progn ,@test-form)
  8.              (progn ,@then-form)
  9.              (progn ,@else-form))))))
  10.  
  11.  
  12. (macroexpand '(our-if 1))
  13. ;; NIL
  14. ;; T
  15.  
  16.  
  17. (macroexpand '(our-if 1 :then (foo) (bar)))
  18. ;; (IF (PROGN 1)
  19. ;;     (PROGN (FOO) (BAR))
  20. ;;     (PROGN))
  21. ;; T
  22.  
  23. (macroexpand '(our-if 1 :then (foo) (bar) :else (baz)))
  24. ;; (IF (PROGN 1)
  25. ;;     (PROGN (FOO) (BAR))
  26. ;;     (PROGN (BAZ)))
  27. ;; 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.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы