LINUX.ORG.RU

[common lisp][некрофилия]Что-то не работает

 ,


0

0

Значит постановка вопроса: есть некая переменная - t или nil.

Надо написать макрос, который будет выполнять при соблюдении некоего условия и значении переменной = nil одно действие и ставить переменную в t, при соблюдени условия и значении переменной = t другое действие, т.е. к примеру:

(if (and trigger cond) (foo))
(if (and (not trigger) cond) (progn (bar) (setq trigger t)))

и так много раз (к примеру, на входе будут списоки (cond act1 act2)

Вот макрос:

http://pastebin.com/Gv62aDN4

Там есть код и пример использования. Проблема в том, что при вызове из самого верху макрос работает, а при вызове из функции пишет ошибку. Вывод такой

A
B
*** - EVAL: variable NAME has no value

Хотя это аргумент функции как-никак. Я в лиспе новичок (точнее - у меня нет практики), так что просьба за быдлокод не пинать.

Если это важно - всё записано в файл и вызывается так - clisp test.lisp

Странный код. Зачем писать макрос разворачивающийся в цикл с eval'ами если можно (нужно) цикл разворачивать в compile-time? eval'ы можно и без макросов делать.

if/progn не нужен. Есть when и unless.

Надеюсь, не буду выглядеть К.О. если напомню про macroexpand-1.

k_andy ★★★
()

Если я всё правильно понял, то

(defmacro lolwut (condition-form variable-form t-form nil-form)
  `(when ,condition-form
     (if ,variable-form
         (progn ,t-form
                (setf ,variable-form nil))
         (progn ,nil-form
                (setf ,variable-form t)))))
CL-USER> (defvar *shit* nil)
*SHIT*
CL-USER> (lolwut (= 1 1)
                 *shit*
                 (format t "Condition is t and variable is t")
                 (format t "Condition is t and variable is nil"))
Condition is t and variable is nilT
CL-USER> (lolwut (= 1 1)
                 *shit*
                 (format t "Condition is t and variable is t")
                 (format t "Condition is t and variable is nil"))
Condition is t and variable is tNIL
CL-USER> (lolwut (= 1 1)
                 *shit*
                 (format t "Condition is t and variable is t")
                 (format t "Condition is t and variable is nil"))
Condition is t and variable is nilT
CL-USER> 

Только тут маленький ахтунг по поводу variable-form - оно будет вычислено несколько раз.

yoghurt ★★★★★
()

Про некрофилию вы неправы. Я за счет лиспа вытянул на сессии пару серьезных предметов.

Так что, учите матчасть.

bk_ ★★
()

Причем тут некрофилия?

power
()

Вариант А

(defmacro lolwut (trigger-form &rest condition-forms)
  `(loop for (cond-form t-form nil-form) in ,@condition-forms do
        (when (eval cond-form)
          (eval (if ,trigger-form t-form nil-form))
          (osetf ,trigger-form (not ,trigger-form)))))
CL-USER> (defvar *yeah* nil)
*YEAH*
CL-USER> (lolwut *yeah* '(((= 1 1) (format t "t form~%") (format t "nil form~%"))
                          ((= 1 1) (format t "t form~%") (format t "nil form~%"))
                          ((= 1 1) (format t "t form~%") (format t "nil form~%"))
                          ((= 1 1) (format t "t form~%") (format t "nil form~%"))
                          ((= 1 2) (format t "t form~%") (format t "nil form~%"))))
nil form
t form
nil form
t form
NIL
CL-USER>
yoghurt ★★★★★
()
Ответ на: Вариант А от yoghurt

Хотя не понятно, чем оно особо различается

different_thing
() автор топика

Вариант Бэ

(defmacro hardcore (trigger-form &rest condition-forms)
  `(progn ,@(loop for (cond-form t-form nil-form) in condition-forms collecting
                 `(when ,cond-form
                    (if ,trigger-form
                        (progn ,t-form
                               (setf ,trigger-form nil))
                        (progn ,nil-form
                               (setf ,trigger-form t)))))))
CL-USER> (defparameter *yeah* nil)
*YEAH*
CL-USER> (hardcore *yeah* 
                   ((= 1 1) (format t "1-t form~%") (format t "1-nil form~%"))
                   ((= 1 1) (format t "2-t form~%") (format t "2-nil form~%"))
                   ((= 1 1) (format t "3-t form~%") (format t "3-nil form~%"))
                   ((= 1 2) (format t "4-t form~%") (format t "4-nil form~%")))
1-nil form
2-t form
3-nil form
NIL
CL-USER> 
yoghurt ★★★★★
()
Ответ на: комментарий от different_thing

Вариант бэ заработал?

Вообще у меня такое ощущение, что я ничего, кроме C и питона никогда не осилю :(

Не сцы, я сам на этом CL пишу второй месяц только

yoghurt ★★★★★
()
Ответ на: комментарий от korvin_

а, ну да

  (let ((res nil)  (query nil) (waswhere nil) (addition ""))
    ;; и потом макра раскрывалась в код с 
    (eval expression-with-waswhere)
    ;; причем expression-with-waswhere даже не заквотированое как я понял

1) eval — функция, т.е:

(defvar a 1)
(defvar b 'a)
(eval b) ; => (evval 'a) => 1
(eval 'b) ; => 'a

2) eval не видит лексических переменных, т.е:

(let ((some-lexic-var t))
  (eval 'some-lexic-var))
выдаст как раз ошибку о неизвестной переменной some-lexic-var

P.S. в LET, если объявляешь переменную со значением nil можно не указывать этого явно, т.е.:

  (let (res  query waswhere (addition ""))

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Спасибо за пояснения. В общем практики у меня мало пока, вот и результат налицо)

different_thing
() автор топика
Ответ на: комментарий от different_thing

но функции-то объявленные через defun объявляются в top-level.

с функциями, объявленными с помощью, например labels та же история

(defun foo ()
  (labels ((bar ()))
    (eval '(bar))))

korvin_ ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.