【发布时间】:2018-07-14 16:30:48
【问题描述】:
我仍在了解宏,虽然我认为我了解“反引号”、“取消引用”和“取消引用拼接”的基础知识,但我认为它们仅在宏中使用/有用。
但是我从 Rosetta 代码(calender task)中发现了这个 Common Lisp 代码,
(defun month-strings (year month)
"Collect all of the strings that make up a calendar for a given
MONTH and YEAR."
`(,(date-calc:center (month-to-word month) (length *day-row*))
,*day-row*
;; We can assume that a month calendar will always fit into a 7 by 6 block
;; of values. This makes it easy to format the resulting strings.
,@ (let ((days (make-array (* 7 6) :initial-element nil)))
(loop :for i :from (date-calc:day-of-week year month 1)
:for day :from 1 :to (date-calc:days-in-month year month)
:do (setf (aref days i) day))
(loop :for i :from 0 :to 5
:collect
(format nil "~{~:[ ~;~2,d~]~^ ~}"
(loop :for day :across (subseq days (* i 7) (+ 7 (* i 7)))
:append (if day (list day day) (list day))))))))
这里的反引号、取消引号和取消引号拼接用于普通函数,它可以创建字符串列表。
虽然我不使用 Scheme,但 Racket 解决方案也有类似的东西,
(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) " ")))))))
我没有测试。
我的问题是,
为什么在函数中需要这样做,用例是什么?
它与宏有何不同?
【问题讨论】:
-
反引号是用于制作 s 表达式(基于嵌套列表的结构)的语法糖。 Lisp 源代码由 s 表达式组成,因此反引号对于宏(输入和输出是代码的函数,采用 s 表达式的形式)很有用。许多 Lisp 数据是由 s-expressions 组成的,因此反引号对于操作数据的函数很有用(当数据是 s-expressions 的形式时)
标签: list scheme common-lisp backquote