2017-05-28 46 views
1

这是我的代码,我有点困惑,为什么我收到这个错误。我的代码只是找到一个二次方程的根。为什么我得到#<undef>不是函数错误?

(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) 

回答

2

我相信你的意思是在正文中添加一个begin你一个武装如果公司的。 display过程具有无效返回值,额外的括号会尝试将该值作为过程应用。您可以通过运行((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))) 
       )    
) 
) 
+0

谢谢。是的,我打算在if的主体中添加一个开始,现在我明白为什么显示会导致错误。它现在有效。 –

2

方案括号是非常特殊的。他们的意思是apply

(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)))) 

不幸的是,在操作位置返回#<undef>表达。实际上,根据规范,它可以返回任何东西,因为它在规范中未定义。 IB您的具体实现,虽然它不是一个功能,所以它是这样的:

((test 'symbol) 4 5); ==> Error: symbol is not a function 

正如你前面看到的具有test一个电话没工作较早所以在操作员位置表情是完全有效的代码,几乎不可能在编译时推理,但是在运行时它将变得很明显,当应用程序获得非函数时不可能继续。

现在有一些宏使用括号来表示应用程序以外的东西,而这些只是必须知道或阅读的文档。一个例子是cond

(cond ((= 3 5) #t) 
     (else #f)) 
; ==> #f 

如果你从来没有见过cond很容易承担((= 3 5) #t)是看它,它不应该因为(= 3 5)工作的表达,当然,也不会计算为一个函数对象但之前布尔值。然而,cond中的每个术语评估它的car,然后评估其余部分中的每个元素,如果它碰巧是一个真正的值。

,以便做更多的表达式并返回最后一个表达式的值使用begin

(begin 1 2 3) 
; ==> 3 

这里评估12显然是死代码,因为它没有做任何事情。因此,其继承使用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) 
相关问题