2009-06-03 13 views
8

Chcę napisać program, aby znaleźć korzenie równania kwadratowego na Schemacie. Użyłem LET dla niektórych powiązań.Używanie Let in Scheme

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

zdefiniowałem Wyróżnik z 4ac ponieważ nie chciałem (* 4 a c). Mimo, że zostały zdefiniowane (4ac (* 4 a c)), to daje mi ten błąd:

expand: unbound identifier in module in: 4ac .

Moje pytanie brzmi: w jaki sposób jest oceniany niech (jakiej kolejności)? A jeśli chcę 4ac w moim let powinienem napisać kolejny wewnętrzny let? Czy jest lepszy sposób to zrobić?

+1

To jest przykład z SICP Lecture/Book! – Nishant

Odpowiedz

27

Użyj let* zamiast .

Różnica między let i let* jest następujący:

let* wiąże zmienne od lewej do prawej. Wcześniejsze wiązania można stosować w nowym wiązaniu dalej w prawo (lub w dół).

let Z drugiej strony może być traktowane jako składniowej cukru (lub makro) dla prostego lambda abstrakcji:

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

jest równoważna

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

Czy możesz skomentować różnicę w kolejności oceny między tymi dwoma? – unj2

+0

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

+2

to nie jest (tylko) o zleceniu oceny, głównie chodzi o zakres. w zwykłym let, zakres każdej zmiennej jest tylko wyrażenie, a nie powiązania. in let *, zakres każdej zmiennej to wyrażenie i każde powiązanie po sobie. – Javier

3

Będziesz potrzebował special let-construct (let*), ponieważ zmienne wewnątrz definicji let odnoszą się do siebie.

To raczej problem zdefiniowania zakresu niż oceniania wyrażenie (W zwykłych let -definitions kolejność oceny nie ma znaczenia, ponieważ wartości mogą nie stosować się nawzajem)

8
  • 4ac jest zmienna o wartości numerycznej, więc (4ac) nie ma znaczenia.

  • LET wiąże wszystkie zmienne, ale zmiennych nie można używać w obliczeniach dla wartości.

To nie działa:

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

przeznaczenie:

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

Przede wprowadza A i B z pierwszego LET. W drugim LET A i B mogą być teraz używane do obliczania C

Lub:

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

Podczas korzystania pozwolić, wiązania nie są widoczne w każdym z ciał. Zamiast tego użyj * let i zobacz dokumentację RNRS, aby uzyskać szczegółowe informacje.