Scheme 为什么我会得到#<;未定义>;这不是函数错误吗?

Scheme 为什么我会得到#<;未定义>;这不是函数错误吗?,scheme,Scheme,这是我的代码,我有点困惑为什么我会收到这个错误。我的代码就是找到一个二次方程的根 (define (roots a b c) (define det (- (* b b) (* 4 a c)) ) (if (> det 0) ( (display (/ (+ (* b -1) (sqrt det)) (* 2 a))) (display (/ (- (* b -1) (sqrt det)) (* 2

这是我的代码,我有点困惑为什么我会收到这个错误。我的代码就是找到一个二次方程的根

(define (roots a b c)
  (define det
    (- (* b b) (* 4 a c))
  )
  (if (> det 0) (
                  (display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
                  (display (/ (- (* b -1) (sqrt det)) (* 2 a)))
                )
  )
  (if (= det 0) (
                   (display (/ (* b -1) (* 2 a)))
                  (display (/ (* b -1) (* 2 a)))
                )
  )
  (if (< det 0) (
                  (display "complex roots")
                  (display (/ (+ (* b -1) sqrt(* det -1)) (* 2 a)))
                  (display (/ (- (* b -1) sqrt(* det -1)) (* 2 a)))
                )               
  )
)

(roots -2 4 5)
(roots -2 4 -5)
(定义(根a b c)
(定义det)
((*4B)(*4C))
)
(如果(>det 0)(
(显示(/(+(*b-1)(sqrt数据))(*2A)))
(显示(/((*b-1)(sqrt数据))(*2A)))
)
)
(如果(=det 0)(
(显示(/(*b-1)(*2A)))
(显示(/(*b-1)(*2A)))
)
)
(如果(
我相信你的意思是在你的单臂if的身体中添加一个
开始。
display
过程有一个无效的返回值,额外的括号将尝试将该值作为过程应用。您可以通过运行
((显示5))
再现错误。使用
begin
将允许您按顺序计算表达式


此代码将显示无任何异常的值:

(define (roots a b c)
  (define det
    (- (* b b) (* 4 a c))
  )
  (if (> det 0) (begin
                  (display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
                  (display (/ (- (* b -1) (sqrt det)) (* 2 a)))
                )
  )
  (if (= det 0) (begin
                   (display (/ (* b -1) (* 2 a)))
                  (display (/ (* b -1) (* 2 a)))
                )
  )
  (if (< det 0) (begin
                  (display "complex roots")
                  (display (/ (+ (* b -1) sqrt(* det -1)) (* 2 a)))
                  (display (/ (- (* b -1) sqrt(* det -1)) (* 2 a)))
                )               
  )
)
(定义(根a b c)
(定义det)
((*4B)(*4C))
)
(如果(>det 0)(开始
(显示(/(+(*b-1)(sqrt数据))(*2A)))
(显示(/((*b-1)(sqrt数据))(*2A)))
)
)
(如果(=det 0)(开始
(显示(/(*b-1)(*2A)))
(显示(/(*b-1)(*2A)))
)
)
(如果(
我相信你的意思是在你的单臂if的身体中添加一个
开始。
display
过程有一个无效的返回值,额外的括号将尝试将该值作为过程应用。您可以通过运行
((显示5))
再现错误。使用
begin
将允许您按顺序计算表达式


此代码将显示无任何异常的值:

(define (roots a b c)
  (define det
    (- (* b b) (* 4 a c))
  )
  (if (> det 0) (begin
                  (display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
                  (display (/ (- (* b -1) (sqrt det)) (* 2 a)))
                )
  )
  (if (= det 0) (begin
                   (display (/ (* b -1) (* 2 a)))
                  (display (/ (* b -1) (* 2 a)))
                )
  )
  (if (< det 0) (begin
                  (display "complex roots")
                  (display (/ (+ (* b -1) sqrt(* det -1)) (* 2 a)))
                  (display (/ (- (* b -1) sqrt(* det -1)) (* 2 a)))
                )               
  )
)
(定义(根a b c)
(定义det)
((*4B)(*4C))
)
(如果(>det 0)(开始
(显示(/(+(*b-1)(sqrt数据))(*2A)))
(显示(/((*b-1)(sqrt数据))(*2A)))
)
)
(如果(=det 0)(开始
(显示(/(*b-1)(*2A)))
(显示(/(*b-1)(*2A)))
)
)
(如果(
方案中的括号非常特殊。它们的意思是应用

(define (test arg) arg)

((test +) 4 5) ; ==> 9
在JavaScript中也是如此:

const plus = (a, b) => a+b; // Needed since + is not a function in JS
const test = arg => arg

test(plus)(4,5) // ==> 9
在代码中,您有:

((display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
 (display (/ (- (* b -1) (sqrt det)) (* 2 a))))
不幸的是,运算符位置中的表达式返回
#
。实际上,根据规范,它可以返回任何内容,因为它在规范中未定义。Ib是您的特定实现,但它不是一个函数,因此它类似于:

((test 'symbol) 4 5); ==> Error: symbol is not a function
正如您在前面看到的,调用
test
之前确实有效,因此运算符位置的表达式是完全有效的代码,几乎不可能在编译时进行推理,但在运行时,当apply获得非函数时,显然不可能继续

现在有一些宏使用括号表示应用程序以外的内容,您只需了解或阅读文档即可。例如
cond

(cond ((= 3 5) #t)
      (else #f))
; ==> #f
如果您以前从未见过cond,那么很容易假设
(=35)#t)
是一个表达式,当然,通过查看它,它不应该起作用,因为
(=35)
不会计算为函数对象,而是布尔值。但是,
cond
中的每个项计算它的
car
,然后依次计算该项其余部分中的每个元素,如果它恰好是真值

要按顺序执行更多表达式并返回上一个表达式的值,请使用
begin

(begin 1 2 3)
; ==> 3
在这里,评估
1
2
显然是死代码,因为它什么都不做。因此,它继承了使用
begin
意味着一种副作用,即返回值不重要,但副作用很重要。我不认为你的功能真的需要副作用:

(define (roots a b c)
  (define det
    (- (* b b) (* 4 a c)))
  (cond ((> det 0)
         (list (/ (+ (* b -1) (sqrt det)) (* 2 a))
               (/ (- (* b -1) (sqrt det)) (* 2 a))))
        ((= det 0)
         (list (/ (* b -1) (* 2 a))))
        ((< det 0)
         (list (/ (+ (* b -1) (make-rectangular 0 (sqrt (* det -1)))) (* 2 a))
               (/ (- (* b -1) (make-rectangular 0 (sqrt (* det -1)))) (* 2 a))))))

(roots -1 4 -4) ; ==> (2 -2)
(roots 1 0 -4)  ; ==> (2)
(roots 4 0 4)   ; ==> (0+1i 0-1i)
(定义(根a b c)
(定义det)
(((*BB)(*4C)))
(条件((>det 0)
(列表(/(+(*b-1)(sqrt det))(*2A))
(/((*b-1)(sqrt数据))(*2A)))
(=det 0)
(列表(/(*b-1)(*2A)))
((2 -2)
(根10-4);==>(2)
(根4 0 4);==>(0+1i 0-1i)

方案中的括号非常特殊。它们的意思是应用

(define (test arg) arg)

((test +) 4 5) ; ==> 9
在JavaScript中也是如此:

const plus = (a, b) => a+b; // Needed since + is not a function in JS
const test = arg => arg

test(plus)(4,5) // ==> 9
在代码中,您有:

((display (/ (+ (* b -1) (sqrt det)) (* 2 a)))
 (display (/ (- (* b -1) (sqrt det)) (* 2 a))))
不幸的是,运算符位置中的表达式返回
#
。实际上,根据规范,它可以返回任何内容,因为它在规范中未定义。Ib是您的特定实现,但它不是一个函数,因此它类似于:

((test 'symbol) 4 5); ==> Error: symbol is not a function
正如您在前面看到的,调用
test
之前确实有效,因此运算符位置的表达式是完全有效的代码,几乎不可能在编译时进行推理,但在运行时,当apply获得非函数时,显然不可能继续

现在有一些宏使用parenthe