?
宏相關語法糖
This is all resolved at the reader level, so the model that gets produced is the same whether you take your code with sugar or without.
Macro | Syntax |
---|---|
quote |
|
quasiquote |
|
unquote |
|
unquote-splice |
|
unpack-iterable |
|
unpack-mapping |
|
?quote 引號,是雙引號下面的那個單引號'
quasiquote 反引號,是左上角波浪線下面的那個引號`
unquote 波浪線 取消引用~
unquote-splice 取消引用并展開 波浪線+@ ~@
unpck-iterable 取消引用并迭代 使用#*
unpack-mapping 取消引用并映射?#**
?quote 引號,是雙引號下面的那個單引號'
直接引用后面的表達式,不執行,有點像python里的單引號和雙引號。hy手冊中的描述:
返回給定的模型而不進行評估。或者更為迂腐的是,quote遵循生成并返回最初調用的模型的代碼。因此,quote充當了模型構造函數的語法糖
(quote a); Equivalent to: (hy.models.Symbol "a")
(quote (+ 1 1)); Equivalent to: (hy.models.Expression [; (hy.models.Symbol "+"); (hy.models.Integer 1); (hy.models.Integer 1)])
?可以直接用單引號代替quote
=> 'a
'a
=> '(+ 1 1)
'(+ 1 1)
quasiquote 反引號,是左上角波浪線下面的那個引號`
跟引號類似,只是表達式里面有些符合要求的會被求值。hy手冊中說:
準引號與引號類似,只是它將模型視為模板,其中某些特殊表達式表示某些代碼應該被求值,并在那里替換其值。這個想法類似于C的sprintf或Python的各種字符串格式構造。
=> (setv x 2)
=> (quasiquote (+ 1 (unquote x))) ; => '(+ 1 2)
'(+ 1 2)=> `(+ 1 ~x)
'(+ 1 2)
可以看到,表達式里面使用unquote的地方,進行了求值操作。如果使用quote引號,那么里面即使用了unquote,也會原封不動的表達出來
=> '(+ 1 ~x)
'(+ 1 ~x)
?unquote 波浪線~ 取消引用
在?quasiquote
?表達式內部使用,用于指示某個部分應該被求值而不是作為字面量。就像前面的例子里,x取消引用,也就是要對x進行求值。記住unquote 波浪線~ 應用在quasiquote反引號表達式內部。也就是有unquote~,表達式前面就應該有quasiquote` 。
看個例子
=> (defmacro set-foo [value]
... `(setv foo ~value))
=> (set-foo (+ 1 2 3))
=> (print foo) ; => 6
6
?unquote-splice(取消引用并展開)
也是在quasiquote反引號內部使用,符號是波浪線后跟?@
?符號?~@
?,與?unquote
?類似,但專門用于列表或向量,將其內容展開為多個元素。
=> (setv X [1 2 3])
=> `[a b ~X c d ~@X e f]
'[a b [1 2 3] c d 1 2 3 e f]
第一個 ~X展開為[1 2 3] 第二個?~@X 展開為1 2 3 ,可見?~@把列表展開了,也就是去掉了列表的中括號[ ]?
unpck-iterable 取消引用并迭代(迭代解包)
符號:unpack-iterable用#* ,hy手冊:
(也稱為splat運算符、星形運算符、自變量擴展、自變量爆炸、自變量收集和可變參數等…)
迭代解包和映射解包允許可迭代或映射對象(分別)向函數提供位置或關鍵字參數。
=> [(unpack-iterable [1 2]) 3 4]
[1 2 3 4]=> [#*[1 2] 3 4]
[1 2 3 4]
提供位置參數
=> (defn f [a b c d] [d c b a])
=> (f 1 2 3 4)
[4 3 2 1]
=> (f #*[1 2 3 4])
[4 3 2 1]
解包在各種上下文中都是允許的,并且可以在一個表達式中解包多次(PEP 3132、PEP 448)。
=> (setv [a #* b c] [1 2 3 4 5])
=> [a b c]
[1 [2 3 4] 5]
=> [#* [1 2] #* [3 4]]
[1 2 3 4]
unpack-mapping 取消引用并映射(映射解包)
用于在宏展開時解包映射(如哈希表),符號:?unpack-mapping用#**?
。
=> (defn f [a b c d] [d c b a])
=> (f 1 2 #** {"c" 3 "d" 4})
[4 3 2 1]
當然解包在各種上下文中都是允許的,并且可以在一個表達式中解包多次。?
=> {#** {1 2} #** {3 4}}
{1 2 3 4}
=> (f #* [1] #* [2] #** {"c" 3} #** {"d" 4})
[4 3 2 1]
?