Scheme 错误:(/)错误的参数类型:#<;未指明>;平方根近似
我正在关注麻省理工学院的SICP讲座,这就是我试图通过Alexandria方法中的Heron找到的数字的平方根近似值。这是我第一次尝试lisp,很抱歉犯了一些错误Scheme 错误:(/)错误的参数类型:#<;未指明>;平方根近似,scheme,lisp,sicp,chicken-scheme,Scheme,Lisp,Sicp,Chicken Scheme,我正在关注麻省理工学院的SICP讲座,这就是我试图通过Alexandria方法中的Heron找到的数字的平方根近似值。这是我第一次尝试lisp,很抱歉犯了一些错误 (define guess 1) (define (avg a b) (/ (+ a b) 2)) (define (try guess x) (if (goodEnough guess x) guess (improve guess x))) (define (improve guess x)
(define guess 1)
(define (avg a b)
(/ (+ a b) 2))
(define (try guess x)
(if (goodEnough guess x)
guess
(improve guess x)))
(define (improve guess x)
(define guess (avg guess (/ x guess)))
(try guess x)
)
(define (goodEnough guess x)
(= guess (avg guess (/ x guess))))
(print (try 1 25))
我正在使用Chicken scheme编译器来打印这个。这是输出:
Error: (/) bad argument type: #<unspecified>
Call history:
1.a.SquareRootApproximation.scm:29: try
1.a.SquareRootApproximation.scm:17: goodEnough
1.a.SquareRootApproximation.scm:27: avg
1.a.SquareRootApproximation.scm:19: improve <--
错误:(/)错误的参数类型:#
通话记录:
1.a.a.scm:29:试试看
1.a.a.scm:17:goodEnough
1.a.S.scm:27:avg
1.a.SquareRootApproximation.scm:19:improve该值在其他语言中基本上是“void”。当某些过程没有任何有用的返回值时(例如,print
将返回此值),它将用作返回值。在某些情况下,它也用作临时占位符值,例如在处理内部定义时
通常情况下,该语言的用户不应看到此临时占位符,但您似乎在该语言中遇到了一个奇怪的边缘情况(祝贺您!这种情况很少发生)。发生此错误的原因是过程中的(define guess(avg guess(/x guess))
同时定义变量并使用该变量。这样做的行为没有得到很好的规定,一些方案实现会像CHICKEN所做的那样(Guile、Gauche、Gambit),而其他方案会给出一个更有意义的错误消息(MIT、Scheme48、Racket)。这是因为内部define
扩展为letrec
,因为它允许定义相互递归的过程,但这产生了一点问题:例如(define a b)(define b a)
应该怎么办
您的意图似乎是使用作为过程输入传递的旧guess变量,因此,您可以使用let
为guess
绑定一个新值,而不是使用define
(这应该如何表现是很好的指定),或者使用不同的名称,就像《新猜想》
我还没有学会let,我还在上第一堂课。也许新的猜测才是正确的方法。谢谢它实际上与新变量一起工作。由于在R5RS和早期的定义中,在lambda
(和派生形式)中,它得到了很好的指定是letrec
不允许在主体之前和R6RS中评估任何变量,之后是letrec*
,允许评估已初始化的变量。当然,所有这些都不允许在同一个lambda
中计算被任何局部define
隐藏的变量letrec
和letrec*
允许生成递归函数,因此在闭包创建时需要存在绑定。在
表单中直接引用任何
的值是“一个错误”的意义上,这是非常明确的。然而,这基本上意味着“实现可以自由地做任何它想做的事情”。本质上,它类似于C语言中的“未定义行为”。任何“错误”都不在规范范围内,导致此类错误的程序可能会运行,也可能不会运行/编译。这是非常依赖于实现的,正如您从我的示例中看到的:MIT、Racket和Scheme48的行为与CHICKEN、Guile、Gambit和Gauche非常不同。