'当'这些实现之间究竟有什么不同?
(define-syntax when
(syntax-rules ()
((_ pred b1 ...)
(if pred (begin b1 ...)))))
VS。
(define (my-when pred b1 ...)
(if pred (begin b1 ...)))
例如,当' my-when'用于此for循环宏:
(define-syntax for
(syntax-rules ()
((_ (i from to) b1 ...)
(let loop((i from))
(my-when (< i to)
b1 ...
(loop (+ i 1)))))))
发生错误:
(for(i 0 10)(display i))
中止!:超出最大递归深度
我不认为&#39;何时&#39;可以作为一个函数实现,但我不知道为什么......
答案 0 :(得分:0)
如果将when
实现为与您一样的过程,则会评估所有参数。在for
实施中,评估将按以下方式处理:
(< i to)
b1 ...
(loop (+ i 1))
&lt; - 这里进入无限循环!my-when
项目1-3可以是反向或未定义的顺序,具体取决于您的实现,但该点是nr。 4.如果将my-when
实现为宏,则宏是第一个要评估的宏。
如果你真的需要用一个程序来实现,那么你需要使用一些延迟技巧,比如thunk。例如:
(define (my-when pred body) (if (pred) (body)))
(my-when (lambda () (< i 10)) (lambda () (display i) (loop (+ i 1))))
答案 1 :(得分:0)
Scheme具有严格的语义。
这意味着在将函数应用于函数之前,将评估所有函数的参数。
宏获取源代码并生成源代码 - 他们不评估任何参数。
(或者,好吧,我想他们这样做了,但他们的参数是语法 - 语言元素 - 而不是你通常认为的值,如数字或字符串。宏编程是元编程。它是&#39; s重要的是要知道你在哪个级别编程。)
在您的示例中,这意味着当type ActionA = {
type: 'A',
a: number
};
type ActionB = {
type: 'B',
b: string
};
type Action = ActionA | ActionB;
type State = number;
function reducer(state: State, action: Action): State {
switch(action.type) {
case 'A' :
return action.a
case 'B' :
return action.b.length
default :
(action: null) // check for exhaustivity
throw `unknown action`
}
}
是一个函数时,my-when
必须先评估(loop (+ i 1))
才能应用my-when
。
这导致无限递归。
当它是一个宏时,my-when
表单首先被替换为等效的if
- 表单
(if (< i to)
(begin
b1 ...
(loop (+ i 1))))
然后评估整个事情,这意味着(loop (+ i 1))
仅在条件为真时进行评估。