Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.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
Scheme 实施方案';仅使用cond的s if子句_Scheme_Lisp_Racket_Sicp - Fatal编程技术网

Scheme 实施方案';仅使用cond的s if子句

Scheme 实施方案';仅使用cond的s if子句,scheme,lisp,racket,sicp,Scheme,Lisp,Racket,Sicp,问题: 考虑一个不执行IF构造但只有一个COND的元计算评估器。路易斯·雷纳 声称if是不必要的,因为我们可以使用元循环评估器评估以下程序: (define (if predicate action alternative) (cond (predicate action) (else alternative))) 解释为什么这不起作用。特别是,假设您使用此if过程来定义阶乘: (define (factorial n) (if (= n 1) 1

问题: 考虑一个不执行IF构造但只有一个COND的元计算评估器。路易斯·雷纳 声称if是不必要的,因为我们可以使用元循环评估器评估以下程序:

(define (if predicate action alternative)
  (cond (predicate action)
        (else alternative)))
解释为什么这不起作用。特别是,假设您使用此if过程来定义阶乘:

(define (factorial n)
  (if (= n 1)
      1
      (* n (factorial (- n 1)))))

使用上面的if语句计算(阶乘3)的结果使程序永远运行,但我不知道为什么。对此的任何提示都将不胜感激!谢谢

a
如果
表达式是一种特殊形式,它不会遵循与正常过程相同的求值规则-因此它不能由过程实现,它必须使用语法转换(例如,使用宏或在您的情况下,更改底层解释器)。要了解这一点,请查看以下简单示例:

(if #t 'ok (/ 1 0))
=> 'ok
由于只计算了表达式的
'ok
部分,因此从未发生过被零除的情况。尝试使用
的实现来计算相同的表达式,如果
,则会得到
除以零的错误


现在您可以看到,如果根据条件的值对
表达式进行不同的计算,则只执行结果或只执行替代项,但决不能同时执行两者。这就是你的
阶乘
示例失败的原因-即使达到基本情况,也会执行另一个分支,从而创建一个无限循环。

如果
表达式是一种特殊形式,它不会遵循与正常过程相同的求值规则-因此它不能由过程实现,它必须使用语法转换(例如,使用宏,或者在您的情况下,更改底层解释器)。要了解这一点,请查看以下简单示例:

(if #t 'ok (/ 1 0))
=> 'ok
由于只计算了表达式的
'ok
部分,因此从未发生过被零除的情况。尝试使用
的实现来计算相同的表达式,如果
,则会得到
除以零的错误


现在您可以看到,如果根据条件的值对
表达式进行不同的计算,则只执行结果或只执行替代项,但决不能同时执行两者。这就是您的
阶乘
示例失败的原因-即使达到基本情况,也会执行另一个分支,从而创建一个无限循环。

请注意,
if/cond
是语法,而不是过程。使用语法、实际定义语法和尝试使用语法是有区别的。为了说明,考虑以下内容:

(+ 1 (- 4 2))
这里我们有一个过程,它取零个或更多的数字,并返回它们的和。我们用两个参数应用了这个过程,第二个参数是表达式
(-42)
,而不是值。请注意,这不会导致违反合同错误,实际计算结果为3。为什么?因为任何不是值的参数首先被简化为值。因此表达式的计算结果为:

(+ 1 (- 4 2))
=> (+ 1 2)
=> 3
回到您定义的
if
过程,同样的规则也适用,因为传递给函数的任何参数(本身不是值)在使用
if
过程之前都将被缩减为值。因此,
(阶乘1)
的计算变成:

(factorial 1)
=> (if (= 1 1) 1 (* 1 (factorial 0)))
=> (if #t 1 (* 1 (factorial 0)))
=> (if #t 1 (* 1 (if (= 0 1) 1 (* 0 (factorial -1)))))
=> (if #t 1 (* 1 (if #f 1 (* 0 (factorial -1)))))
=> ... (endless loop to negative infinity)
这不同于使用
if
语法,其中求值是短路的,这意味着只有当谓词为false时才会求值
else
情况。比如说,

(if #t 1 (+ 1 'a))

willnot在尝试添加数字和符号时抛出错误,因为它首先不会计算else表达式(因为谓词的计算结果为true)。因此,它返回1。

注意,
if/cond
是语法,而不是过程。使用语法、实际定义语法和尝试使用语法是有区别的。为了说明,考虑以下内容:

(+ 1 (- 4 2))
这里我们有一个过程,它取零个或更多的数字,并返回它们的和。我们用两个参数应用了这个过程,第二个参数是表达式
(-42)
,而不是值。请注意,这不会导致违反合同错误,实际计算结果为3。为什么?因为任何不是值的参数首先被简化为值。因此表达式的计算结果为:

(+ 1 (- 4 2))
=> (+ 1 2)
=> 3
回到您定义的
if
过程,同样的规则也适用,因为传递给函数的任何参数(本身不是值)在使用
if
过程之前都将被缩减为值。因此,
(阶乘1)
的计算变成:

(factorial 1)
=> (if (= 1 1) 1 (* 1 (factorial 0)))
=> (if #t 1 (* 1 (factorial 0)))
=> (if #t 1 (* 1 (if (= 0 1) 1 (* 0 (factorial -1)))))
=> (if #t 1 (* 1 (if #f 1 (* 0 (factorial -1)))))
=> ... (endless loop to negative infinity)
这不同于使用
if
语法,其中求值是短路的,这意味着只有当谓词为false时才会求值
else
情况。比如说,

(if #t 1 (+ 1 'a))

willnot在尝试添加数字和符号时抛出错误,因为它首先不会计算else表达式(因为谓词的计算结果为true)。因此,它返回1。

我在阶乘循环中打印了n,n从3减少到负无穷大。即使在几个循环后n已经等于0,程序仍然没有停止。我在阶乘循环中打印了n,n从3减少到负无穷大。即使n在几个循环后已经等于0,程序仍然没有停止。谢谢!这绝对有帮助。谢谢!这绝对有帮助。