List 正常函数中的反引号、反引号和反引号拼接
我仍在理解宏的过程中,虽然我认为我理解“反引号”、“反引号”和“反引号拼接”的基本知识,但我认为它们只在宏中使用/有用 然而,我在Rosetta代码(the)中遇到了这个常见的Lisp代码 在这里,反引号、反引号和反引号拼接在普通函数中使用,用于创建字符串列表 虽然我不使用Scheme,但球拍解决方案也有相似之处List 正常函数中的反引号、反引号和反引号拼接,list,scheme,common-lisp,backquote,List,Scheme,Common Lisp,Backquote,我仍在理解宏的过程中,虽然我认为我理解“反引号”、“反引号”和“反引号拼接”的基本知识,但我认为它们只在宏中使用/有用 然而,我在Rosetta代码(the)中遇到了这个常见的Lisp代码 在这里,反引号、反引号和反引号拼接在普通函数中使用,用于创建字符串列表 虽然我不使用Scheme,但球拍解决方案也有相似之处 (define days (let ([? (if (= mn 12) (λ(x y) y) (λ(x y) x))]) (round (/ (- (find-se
(define days
(let ([? (if (= mn 12) (λ(x y) y) (λ(x y) x))])
(round (/ (- (find-seconds 0 0 12 1 (? (+ 1 mn) 1) (? yr (+ 1 yr))) s)
60 60 24))))
(list* (~a mname #:width 20 #:align 'center) "Su Mo Tu We Th Fr Sa"
(map string-join
(nsplit 7 `(,@(make-list pfx " ")
,@(for/list ([d days])
(~a (+ d 1) #:width 2 #:align 'right))
,@(make-list (- 42 pfx days) " ")))))))
我没有测试
我的问题是,
为什么这在函数中是必需的,用例是什么
它与宏有何不同 quasikote、unquote和unquote拼接只是引用数据、
list
和cons
组合的语法糖。想象一下:
`(,a b c) ; == (cons a '(b c))
`(a b ,c) ; == (list 'a 'b c)
`(a b ,@c d) ; == (cons 'a (cons 'b (append c '(d))))
这些都是小而琐碎的例子,所以你可以想象右手边可能会变得非常复杂,但是很高兴知道,Quasikote魔法会在需要时生成新的cons,并保持文本的尾部。因此,在第一种情况下,使用准连续表达式的ncoc
将不起作用,但在第二种和第三种情况下,因为在这些情况下,最后的cons需要是新的
如果您有一个创建列表结构的函数,quasiquote将使代码更加清晰一致,因为表单看起来更像结果。它与宏没有区别,因为两者都创建列表结构。宏与结果的不同之处在于发生了什么。在函数中返回值,在宏代码中替换
您可以通过macroexpand
检查使用宏后发生的情况:
(macroexpand '`(,a ,b ,@c))
; ==> (cons a (cons b c))
; ==> t
准引号(QQ)是Scheme中的列表构造函数
它比引号(')、列表或cons更灵活,因为它允许将符号与表达式求值混合使用
QQ有两种辅助机制:
(define b 5)
(define s (list 1 2))
请注意以下表达式值的差异:Quote、Quote
输入:
'(a b c)
`(a b c)
输出
> (a b c)
> (a b c)
> (a ,b c)
> (a 5 c)
> (a ,s c)
> (a (1 2) c)
> (a ,@s c)
> (a 1 2 c)
输入
输出
> (a b c)
> (a b c)
> (a ,b c)
> (a 5 c)
> (a ,s c)
> (a (1 2) c)
> (a ,@s c)
> (a 1 2 c)
输入
输出
> (a b c)
> (a b c)
> (a ,b c)
> (a 5 c)
> (a ,s c)
> (a (1 2) c)
> (a ,@s c)
> (a 1 2 c)
输入
输出
> (a b c)
> (a b c)
> (a ,b c)
> (a 5 c)
> (a ,s c)
> (a (1 2) c)
> (a ,@s c)
> (a 1 2 c)
资料来源:我参加的汇编课程,Backquote 请参阅上的CLHS 示例 该示例类似于此代码:
CL-USER 14 > (let ((a 1)
(b 2)
(c '(3 4 5)))
`(,a ; a gets evaluated and put in
,b ; b gets evaluated and put in
,@c)) ; c gets evaluated and spliced in
(1 2 3 4 5)
上述代码的效果类似于使用函数list*
CL-USER 15 > (let ((a 1)
(b 2)
(c '(3 4 5)))
(list* a b c))
(1 2 3 4 5)
你使用哪种版本主要取决于你的品味
list*
创建第一个值的列表,并将它们放在最后一个值的前面,最后一个值应该是一个列表
列表创建
有许多方法和样式可以创建列表。这里有两个:
cons
,list
,list*
,append
。。。当有许多元素需要计算时,这尤其有用,
,,@
,,.
进行评估。当存在包含固定对象和几个要计算的对象的嵌套列表时,这一点尤其有用CL-USER 20 > (let ((a 1)
(b 2)
(c '(3 4 5)))
`#(,a
,b
,@c))
#(1 2 3 4 5)
反引号是生成s表达式(嵌套的基于列表的结构)的语法糖。Lisp源代码由s表达式组成,因此反引号对于宏(输入和输出为代码的函数,其形式为s表达式)非常有用。许多Lisp数据都是由s表达式构成的,因此反引号对于操作数据的函数(当数据是s表达式形式时)非常有用。值得注意的是,尽管问题引用scheme和这些示例在scheme中工作,这个问题还引用了通用的Lisp,因为在反引号外使用逗号是非法的,所以这些都不起作用。1) 我不是匿名的这是我的真名。2) 在scheme中,如果您输入
”(a,b)
,您将得到(a,b)
,即(a(unquote b))
的语法糖。如果我在(sbcl)Common Lisp中尝试相同的方法,我会得到一个错误:逗号不在反引号内
,类型为SB-INT:SIMPLE-READER-error
。我会对陌生人或同事说。我不认为这个短语是猛击或侵略性的。如果问题只是关于计划,那么这将是一个非常好的例子。scheme和Common Lisp在这方面的差异很小,也很微妙,这并不能真正保证对一个问题的新答案,而不是语言之间的差异。macroexpand
东西实际上不起作用,或者通常不有用。由于backquote表单的表示形式未定义,因此未定义应将其读入宏表单。'just syntax sugar'->概念上,而不是字面上。@Rain