Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 在宏观定义中困惑_Macros_Common Lisp_Sicp_Lazy Sequences - Fatal编程技术网

Macros 在宏观定义中困惑

Macros 在宏观定义中困惑,macros,common-lisp,sicp,lazy-sequences,Macros,Common Lisp,Sicp,Lazy Sequences,我想在SICP第3.5.1节中实现惰性流 首先,我定义了这两个函数 (defmacro delay (form) `(lambda () ,form)) (defun force (form) (when form (funcall form))) 当我们打电话时: (force (delay '(+ 1 2))) ;;=> (+ 1 2) (force (delay (+ 1 2))) ;;=> 3 那就行了。然后我继续定义“流氓”,但这次有了 似乎有两种方

我想在SICP第3.5.1节中实现惰性流

首先,我定义了这两个函数

(defmacro delay (form)
  `(lambda () ,form))

(defun force (form)
  (when form
    (funcall form)))
当我们打电话时:

(force (delay '(+ 1 2)))
;;=> (+ 1 2)

(force (delay (+ 1 2)))
;;=> 3
那就行了。然后我继续定义“流氓”,但这次有了 似乎有两种方式:

(defmacro stream-cons (a b)
  `(cons ,a ,(delay b)))

(defmacro stream-cons (a b)
  `(cons ,a (delay ,b)))
我不认为他们有什么不同,但我错了!第一版 是错误的版本,调用时:

(force (cdr (stream-cons 'a (progn (print "hello") 2))))
;;=> (PROGN (PRINT "hello") 2)

(macroexpand '(stream-cons 'a (progn (print "hello") 2)))
;;=> (CONS 'A #<CLOSURE (LAMBDA # :IN STREAM-CONS) {25ABB3A5}>)
(force (cdr (stream-cons 'a (progn (print "hello") 2))))
;; 
;; "hello" 
;; => 2

(macroexpand '(stream-cons 'a (progn (print "hello") 2)))
;;=> (CONS 'A (DELAY (PROGN (PRINT "hello") 2)))
现在,我很困惑。谁能帮我弄清楚不同的地方 那两个呢?非常感谢


我的环境:Windows 32位,SBCL 1.1.4这是理解宏的一个重要概念

问题是,
,(延迟b)
在宏扩展时进行评估,即
lambda
在适当的位置创建,并包裹在传递给它的文本值(即符号列表)上。所以你得到了一个常量函数,它总是返回相同的值——一个恰好是你的代码的列表

你可以这样想象:

,(delay '(progn (print "hello") 2)) => (lambda () '(progn (print "hello") 2))
在第二种变体
(延迟,b)

这里需要注意的是,宏调用的参数是逐字传递的,没有计算。因此,
delay
有效地接收一个被引用的列表(
”(progn(打印“hello”)2)
)。逗号的作用是在它们满足时取消引用

(delay ,'(progn (print "hello") 2)) => (delay (progn (print "hello") 2))