问题描述
说我在lisp中有两个列表
(setq a '(p q))
(setq b '(1 2))
(car a) is p
(car b) is 1
现在我想定义一个符号'(测试p 1),但是如果我在下面使用
(setq c '(test (car a) (car b)))
我得到'(测试(汽车a)(汽车b)) 这是可以理解的,但我只想知道如何将(汽车a)替换为p,将(汽车b)替换为1,并形成新的符号'(test p 1)
谢谢
解决方法
如果要列出列表,则所需的功能为list
:
(list 'test (car a) (car b))`
将是列表(test p 1)
。
请注意,quote
(缩写为'
,所以'(x)
与(quote (x))
相同的目的只是告诉评估者,后面的是文字数据,而不是码。因此,在(list 'test ...)
中,它与(list (quote test) ...)
相同,然后quote
告诉评估者test
被用作文字数据,而不是绑定名称,同样,'(p q)
的意思是“这是一个包含元素p
和q
的文字列表”,而(p q)
的意思是“这是一种评估形式,其含义取决于什么p
是')
首先,setq
不应用于未绑定变量。您可以对已建立的变量使用setq
。另外,对于全局变量,您应该使用*earmuffs*
。
(defparameter *a* '(p q))
(defparameter *b* '(1 2))
(car *a*) ; ==> p
(car *b*) ; ==> 1
引号将使用引号结构作为数据。这意味着您在写expr
的所有'expr
都不会对数据进行逐字评估。使用cons
创建新列表。例如。
;; creates/updates binding *x* to point at the newly created list (test p 1)
(defparameter *c* (cons 'test
(cons (car *a*)
(cons (car *b*)
'()))))
cons
是基元,但是CL还有其他几种创建列表的方法。例如。与功能list
相同:
;; creates/updates binding *x* to point at the newly created list (test p 1)
(defparameter *c* (list 'test (car *a*) (car *b*)))
第二,使用quasiquote
/ unquote
/ unquote-splice
使结构变得更复杂。
;; creates/updates binding *x* to point at the newly created list (test p 1)
(defparameter *c* `(test,(car *a*),(car *b*)))
;; more complex example
(defmacro my-let ((&rest bindings) &body body)
`((lambda,(mapcar #'car bindings),@body),(mapcar #'cadr bindings)))
(macroexpand-1 '(my-let ((a 10) (b 20)) (print "hello") (+ (* a a) (* b b))))
; ==> ((lambda (a b)
; (print "hello")
; (+ (* a a) (* b b)))
; (10 20))
请注意,这只是用cons
,list
和append
制成的相同结构的糖。可能已对其进行了优化,以减少对内存的使用,因此将共享结构。例如。过程中的 `(,x b c)
将执行(cons x '(b c))
,这意味着如果创建两个版本,则它们的cdr
将是eq
,并且应避免对这些部分进行突变。
要完成tfb的回答,您可以编写
class TestSpider:
name = "test"
def __init__(self,item,*args,**kwargs):
self.item = item
def start_requests(self):
yield scrapy.Request('https://example.com/',callback=self.parse)
def parse(self,response):
// just fake response here!
response.css('div li')
yield self.item
这与
完全相同`(test,(car a),(car b)