2017-05-28 2 views
1

Das ist mein Code und ich bin etwas verwirrt, warum ich diesen Fehler erhalte. Mein Code ist nur, um die Wurzeln für eine quadratische Gleichung zu finden.Warum bekomme ich eine # <undef> ist kein Funktionsfehler?

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

Antwort

2

Ich glaube, Sie bedeuten ein begin in dem Körper Ihres einarmigen wenn die hinzuzufügen. Die display-Prozedur hat einen ungültigen Rückgabewert und die zusätzlichen Klammern versuchen, den Wert als Prozedur anzuwenden. Sie können den Fehler reproduzieren, indem Sie ((display 5)) ausführen. Mit begin können Sie stattdessen die Ausdrücke in der Reihenfolge auswerten.


Dieser Code wird die Werte ohne Ausnahmen angezeigt:

(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

Vielen Dank.Ja, ich wollte einen Anfang im Körper des ifs hinzufügen und jetzt sehe ich, warum die Anzeige den Fehler verursacht hat. Es funktioniert jetzt. –

2

Die Klammern in Schema sind sehr speziell. Sie bedeuten apply:

(define (test arg) arg) 

((test +) 4 5) ; ==> 9 

Das gleiche in JavaScript:

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

test(plus)(4,5) // ==> 9 

In Ihrem Code Sie haben:

((display (/ (+ (* b -1) (sqrt det)) (* 2 a))) 
(display (/ (- (* b -1) (sqrt det)) (* 2 a)))) 

Leider ist der Ausdruck in Bedienerposition Rückkehr #<undef>. Eigentlich entsprechend der Spezifikation kann alles zurückgeben, weil es undefined in der Spezifikation ist. Ib Ihre spezielle Implementierung obwohl es keine Funktion, so es heißt:

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

Wie Sie bereits gesehen haben einen Aufruf an test mit früher funktioniert so Ausdrücke in Bedienerposition sind perfekt gültige Code und fast unmöglich, bei der Kompilierung zur Vernunft über , aber in der Laufzeit wird es offensichtlich, dass es nicht möglich ist, fortzufahren, wenn die Anwendung eine Nicht-Funktion erhält.

Jetzt gibt es Makros, die Klammern für etwas anderes als Anwendung verwenden, und diese müssen Sie nur wissen oder lesen Sie die Dokumentation für. Ein Beispiel dafür ist cond

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

Wenn Sie noch nie cond gesehen haben, bevor es einfach ist, ein Ausdruck anzunehmen ((= 3 5) #t) ist und natürlich durch Blick auf sie es nicht, da (= 3 5) funktionieren sollte zu einem Funktionsobjekt nicht bewerten würde, sondern ein boolesch. Jedoch bewertet jedes Glied in cond es car dann jedes Element im Rest des Ausdruckes, wenn es ein echter Wert war.

Um weitere Ausdrücke, um zu tun und den Wert des letzten Ausdrucks zurückgeben verwendet man begin:

(begin 1 2 3) 
; ==> 3 

Hier 1 Bewertung und 2 ist eindeutig toter Code, da er nichts tun. So erbt er, dass die Verwendung begin einen Nebeneffekt impliziert, bei dem der Rückgabewert keine Rolle spielt, aber der Nebeneffekt ist. Ich glaube nicht, dass Ihre Funktion wirklich Nebenwirkungen benötigt:

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