2009-06-03 13 views
8

Quiero escribir un programa para encontrar las raíces de la ecuación cuadrática en Scheme. Usé LET para ciertas ataduras.Usando 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))))) 

que define el discriminante con 4ac ya no quería (* 4 a c). A pesar de que he definido (4ac (* 4 a c)), es que me da este error:

expand: unbound identifier in module in: 4ac .

Mi pregunta es ¿cómo se deja evaluado (qué orden)? Y si quiero 4ac en mi let ¿debo escribir otro interior let? ¿Hay una mejor manera de hacer esto?

+1

¡Este es un ejemplo de SICP Lecture/Book! – Nishant

Respuesta

27

Use let* en lugar de let.

La diferencia entre let y let* es la siguiente:

let* une las variables de izquierda a derecha. Los enlaces anteriores se pueden usar en enlaces nuevos más hacia la derecha (o hacia abajo).

let por el contrario puede ser pensado como el azúcar sintáctica (o macro) de la abstracción lambda sencilla:

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

es equivalente a

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

¿Podría comentar la diferencia del orden de evaluación entre los dos? – unj2

+0

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

+2

no es (solo) sobre el orden de evaluación, se trata principalmente de alcance. en el plano, el alcance de cada variable es solo la expresión, no las consolidaciones. en let *, el alcance de cada variable es la expresión y cada enlace después de sí mismo. – Javier

3

Usted necesitará un special let-construct (let*) aquí ya que las variables dentro de la definición de let se refieren entre sí.

Es más bien un problema de definir un ámbito de aplicación que de la evaluación de una expresión (En habituales let -Definiciones, el orden de evaluación no importa ya que los valores no pueden usar el uno al otro)

8
  • 4ac es una variable con un valor numérico, por lo que (4ac) no es significativo.

  • LET vincula todas las variables, pero las variables no se pueden usar en los cálculos para los valores.

Esto no funciona:

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

Uso:

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

anterior introduce A y B con el primer LET. En la segunda LET tanto A como B ahora se puede utilizar para calcular C

O:

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

Cuando se utiliza vamos, los enlaces no son visibles en cualquiera de los cuerpos. Use let * en su lugar y vea los documentos RNRS para más detalles.