HY lisp quote unquote等学习

宏相关语法糖

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

'FORM

quasiquote

`FORM

unquote

~FORM

unquote-splice

~@FORM

unpack-iterable

#* FORM

unpack-mapping

#** FORM

 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]

  • 11
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值