2009-06-03 9 views
8

Ich möchte ein Programm schreiben, um die Wurzeln der quadratischen Gleichung in Scheme zu finden. Ich habe LET für bestimmte Bindungen verwendet.Mit Let in Schema

(define roots-with-let 
    (λ (a b c) 
    (let ((4ac (* 4 a c)) 
      (2a (* 2 a)) 
      (discriminant (sqrt (- (* b b) (4ac))))) 
     (cons (/ (+ (- b) discriminant) 2a) 
      (/ (- (- b) discriminant) 2a))))) 

I definiert die Diskriminante mit 4ac da ich nicht (* 4 a c) wollte. Auch wenn ich (4ac (* 4 a c)) definiert haben, wird es mir diesen Fehler geben:

expand: unbound identifier in module in: 4ac .

Meine Frage ist, wie wird ausgewertet lassen (welcher Reihenfolge)? Und wenn ich 4ac in meinem let will, sollte ich einen anderen inneren let schreiben? Gibt es einen besseren Weg, dies zu tun?

+1

Dies ist ein Beispiel von SICP Lecture/Book! – Nishant

Antwort

27

Verwenden Sie let* anstelle von let.

Der Unterschied zwischen let und let* ist folgende:

let* bindet Variablen von links nach rechts. Frühere Bindungen können in neuer Bindung weiter rechts (oder unten) verwendet werden.

(let ((a exp1) 
     (b exp2)) 
    exp) 

ist

((lambda (a b) 
    exp) 
exp1 exp2) 
+1

Könnten Sie bitte den Unterschied der Bewertungsreihenfolge zwischen den beiden kommentieren? – unj2

+0

http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_sec_11.4.6 – Javier

+2

ist es nicht (nur) über die Reihenfolge der Auswertung, es geht vor allem um Umfang. In der Ebene ist der Umfang jeder Variablen nur der Ausdruck, nicht die Bindungen. In let * ist der Gültigkeitsbereich jeder Variablen der Ausdruck und jede Bindung nach sich selbst. – Javier

3

Sie eine special let-construct (let* müssen gleichwertig:

let auf der anderen Seite kann als syntaktischer Zucker (oder Makro) für einfache Lambda-Abstraktion gedacht werden) da die Variablen innerhalb der Let-Definition aufeinander verweisen.

Es ist eher ein Problem der Definition eines Bereichs als der Auswertung eines Ausdrucks (In üblichen let -Definitionen, wird die Reihenfolge der Auswertung keine Rolle, da die Werte können einander nicht verwenden)

8
  • 4ac ist eine Variable mit einem numerischen Wert, so (4ac) ist nicht sinnvoll.

  • LET bindet alle Variablen, aber die Variablen können nicht in den Berechnungen für die Werte verwendet werden.

funktioniert das nicht:

(let ((a 1) (b 1) (c (* a b))) 
    c) 

Verwendung:

(let ((a 1) (b 1)) 
    (let ((c (* a b))) 
    c)) 

Above stellt A und B mit dem ersten LET. In den beiden Ein zweiter LET und B kann nun verwendet werden, C. zu berechnen

Oder:

(let* ((a 1) (b 1) (c (* a b))) 
    c) 
2

Wenn Sie lassen, die Bindungen in einem der Körper nicht sichtbar sind. Verwenden Sie stattdessen let * und sehen Sie sich die RNRS-Dokumentation für Details an.