Understanding nested quotes for game-action macro from http://lisperati.planvita.com/actions.html

38 views
Skip to first unread message

Iakiv

unread,
Feb 15, 2013, 10:02:50 PM2/15/13
to clojure...@googlegroups.com
Ребята, 

Вот прочитал я http://lisperati.planvita.com/... И до сих пор не могу осилить вот этот макрос (взят отсюда http://lisperati.planvita.com/actions.html):
(defspel game-action [command subj obj place & args]
 
`(defspel ~command [subject# object#]
     
`(spel-print (cond (and (= location '~'~place)
                             
(= '~subject# '~'~subj)
                             
(= '~object# '~'~obj)
                             
(have? '~'~subj))
                       
~@'~args
                       
:else '(i cannot ~'~command like that -)))))

Который потом используется как 
(game-action weld chain bucket attic
   
(cond (and (have? 'bucket) (def chain-welded true))
             
'(the chain is now securely welded to the bucket -)
         
:else '(you do not have a bucket -)))

(game-action dunk bucket well garden
             
(cond chain-welded
                   
(do (def bucket-filled true)
                       
'(the bucket is now full of water))
                   
:else '(the water level is too low to reach -)))

Здесь defspel - это просто алиас для defmacro.

Идея макроса была в том чтобы заменить им функции:
(defn weld [subject object]
 
(cond (and (= location 'attic)
             
(= subject 'chain)
             
(= object 'bucket)
             
(have? 'chain)
             
(have? 'bucket)
             
(not chain-welded))
       
(do (def chain-welded true)
           
'(the chain is now securely welded to the bucket -))
       
:else '(you cannot weld like that -)))
(defn dunk [subject object]
 
(cond (and (= location 'garden)
             
(= subject 'bucket)
             
(= object 'well)
             
(have? 'bucket)
             chain-welded
)
       
(do (def bucket-filled true)
           
'(the bucket is now full of water))
       
:else '(you cannot dunk like that -)))

Кто то может помочь с обьяснениям как этот макрос работает? Все эти вложеные куоты меня запутали... 

Читал уже вот это - http://blog.8thlight.com/colin-jones/2012/05/22/quoting-without-confusion.html -  не помоголо...

macroexpand-1 меня пугает...

вот что он выдает для weld гейм-екшена:

(clojure-magic-game.core/defspel weld [subject__1058__auto__ object__1059__auto__] (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure-magic-game.core/spel-print)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/cond)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/and)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/=)) (clojure.core/list (quote clojure-magic-game.core/location)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote attic)))))))) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/=)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list subject__1058__auto__)))) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote chain)))))))) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/=)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list object__1059__auto__)))) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote bucket)))))))) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure-magic-game.core/have?)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote chain))))))))))) (quote ((cond (and (have? (quote bucket)) (def chain-welded true)) (quote (the chain is now securely welded to the bucket -)) :else (quote (you do not have a bucket -))))) (clojure.core/list :else) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure-magic-game.core/i)) (clojure.core/list (quote clojure-magic-game.core/cannot)) (clojure.core/list (quote weld)) (clojure.core/list (quote clojure-magic-game.core/like)) (clojure.core/list (quote clojure-magic-game.core/that)) (clojure.core/list (quote clojure.core/-))))))))))))))

Даже если убрать для читабельности неймспейсы и индентировать вывод получиться что то очень далекое от возможностей моего понимания... По крайней мере на первый взгляд...

(defspel weld [subject__1058__auto__ object__1059__auto__] 
  (seq (concat 
         (list (quote spel-print)) 
         (list (seq (concat 
                      (list (quote cond)) 
                      (list (seq (concat 
                                   (list (quote and)) 
                                   (list (seq (concat 
                                                (list (quote =)) 
                                                (list (quote location)) 
                                                (list (seq (concat 
                                                             (list (quote quote)) 
                                                             (list (quote attic)))))))) 
                                   (list (seq (concat (list (quote =)) 
                                                      (list (seq (concat 
                                                                   (list (quote quote)) 
                                                                   (list subject__1058__auto__)))) 
                                                      (list (seq (concat 
                                                                   (list (quote quote)) 
                                                                   (list (quote chain)))))))) 
                                   (list (seq (concat 
                                                (list (quote =)) 
                                                (list (seq (concat 
                                                             (list (quote quote)) 
                                                             (list object__1059__auto__)))) 
                                                (list (seq (concat 
                                                             (list (quote quote)) 
                                                             (list (quote bucket)))))))) 
                                   (list (seq (concat 
                                                (list (quote have?)) 
                                                (list (seq (concat 
                                                             (list (quote quote)) 
                                                             (list (quote chain))))))))))) 
                      (quote ((cond 
                                (and 
                                      (have? (quote bucket)) 
                                      (def chain-welded true)) 
                                (quote (the chain is now securely welded to the bucket -)) 
                                :else (quote (you do not have a bucket -))))) 
                      (list :else) 
                      (list (seq (concat 
                                   (list (quote quote)) 
                                   (list (seq (concat 
                                                (list (quote i)) 
                                                (list (quote cannot)) 
                                                (list (quote weld)) 
                                                (list (quote like)) 
                                                (list (quote that)) 
                                                (list (quote -))))))))))))))

Vinzent

unread,
Mar 10, 2013, 8:45:48 AM3/10/13
to clojure...@googlegroups.com
Все эти seq и concat'ы в макроэкспанде генерируются обратной кавычкой и анквотами, например:

'(`() `(~foo)) ;=>
((clojure.core/list) (clojure.core/seq (clojure.core/concat (clojure.core/list foo))))

Кавычка с анквотом '~ используется, когда нужно вставить в экспанд макроса закавыченный символ, передающийся параметром:

(let [sym (symbol "foo")] `(~sym))  ;=> (foo) -- после подстановки Clojure попытается заэвалить foo
(let [sym (symbol "foo")] `('~sym)) ;=> ((quote foo)) -- то же, что и ('foo)

Двойные '~ возникают из-за того, что внутри одного макроса объявляется другой макрос (соответственно и закавычиваний тоже два), вот тут я набросал несколько примеров с макроэкспандами:


Хотя вообще таких макросов конечно почти никто не пишет почти никогда :)

Vinzent

unread,
Mar 10, 2013, 8:48:21 AM3/10/13
to clojure...@googlegroups.com
Да, кстати: в кложерной джаббер-конференции на вопросы обычно отвечают гораздо быстрее - заходите, если вдруг что :)

Iakiv Kramarenko

unread,
Mar 12, 2013, 12:39:35 PM3/12/13
to clojure...@googlegroups.com
Большое спасибо за обьсянения) 
По крайней мере теперь понял зачем нужно '~ :)

Примеры с cljbin понял не все... То есть технически понимаю, но в голове не откладывается так как надо) 
Ну ничего, действительно, надеюсь не пригодиться в реальной жизни) А вдруг что разберусь на реальном примере) 

 


2013/3/10 Vinzent <ru.vi...@gmail.com>
Да, кстати: в кложерной джаббер-конференции на вопросы обычно отвечают гораздо быстрее - заходите, если вдруг что :)

--
Вы получили это сообщение, так как подписаны на группу "Clojure Russian".
Чтобы отказаться от подписки на эту тему, перейдите на страницу https://groups.google.com/d/topic/clojure-russian/UZ2YAaeTh9Y/unsubscribe?hl=ru.
Чтобы отказаться от подписки на эту группу и все входящие в нее темы, отправьте электронное письмо на адрес clojure-russi...@googlegroups.com.

Подробнее о функциях можно узнать на странице https://groups.google.com/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages