2017-05-28 1 views
1

Ceci est mon code et je suis légèrement confus pourquoi je reçois cette erreur. Mon code est juste pour trouver les racines d'une équation quadratique.Pourquoi je reçois un # <undef> n'est pas une erreur de fonction?

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

Répondre

2

Je crois que vous vouliez ajouter un begin dans le corps de votre armée un si ce. La procédure display a une valeur de retour vide et les parenthèses supplémentaires vont essayer d'appliquer la valeur en tant que procédure. Vous pouvez reproduire l'erreur en exécutant ((display 5)). L'utilisation de begin vous permettra d'évaluer les expressions en séquence.


Ce code affiche les valeurs sans aucune exception:

(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

Merci.Oui, je voulais ajouter un début dans le corps de la si et maintenant je vois pourquoi l'affichage a causé l'erreur. Ça fonctionne maintenant. –

2

Les parenthèses dans le schéma sont très spéciaux. Ils veulent dire apply:

(define (test arg) arg) 

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

Le même en JavaScript:

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

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

Dans votre code que vous avez:

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

Malheureusement, l'expression en position opérateur retour #<undef>. En fait accoring à la spécification, il peut retourner quoi que ce soit car son indéfini dans la spécification. Ib votre implémentation particulière si ce n'est pas une fonction il est comme:

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

Comme vous avez vu plus tôt avoir un appel à test ne travail plus tôt si les expressions dans la position de l'opérateur est un code parfaitement valide et presque impossible de raisonner sur au moment de la compilation , mais en cours d'exécution, il deviendra évident qu'il n'est pas possible de continuer quand apply obtient une fonction non.

Maintenant, il existe des macros qui utilisent des parenthèses pour autre chose que l'application et il vous suffit de connaître ou de lire la documentation. Un exemple est cond

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

Si vous ne l'avez jamais vu cond avant qu'il est facile de supposer ((= 3 5) #t) est une expression et bien sûr en le regardant, il ne devrait pas fonctionner car (= 3 5) n'évaluerait pas à un objet de fonction mais une booléen Cependant chaque terme dans cond évalue c'est car alors chaque élément dans le reste du terme dans l'ordre s'il s'est avéré être une vraie valeur.

Pour faire plus d'expressions dans l'ordre et retourner la valeur de la dernière expression on utilise begin:

(begin 1 2 3) 
; ==> 3 

Ici 1 et évaluent 2 est un code bien mort car il ne fait rien. Ainsi, son héritage que l'utilisation begin implique un effet secondaire où la valeur de retour est sans importance, mais l'effet secondaire est. Je ne pense pas que votre fonction a vraiment besoin d'effets secondaires:

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