Soy nuevo en Scheme; Estoy escribiendo un programa que define recursivamente la multiplicación en términos de suma repetida:

(define multiply 
  (lambda (a b) 
    (if (= b 0) 
        0 
        (+ a (multiply(a, (- b 1)))))))

Sin embargo, cuando intento ejecutar el programa, recibo el mensaje de error:

;Unbound variable: unquote

¿A qué se refiere el mensaje de error y cómo puedo rectificarlo?

3
skeletonsaurus 29 dic. 2016 a las 23:10

3 respuestas

La mejor respuesta

Como estás familiarizado con el lenguaje familiar algol (python), puedo decirte que la familia lisp tiene una sintaxis diferente:

fun(a, b, c)

Está escrito así:

(fun a b c)

Por lo tanto, la fuente de su error es que la coma y los paréntesis se interpretan de manera diferente en los idiomas lisp.

¿A qué se refiere el mensaje de error? En la familia lisp, en realidad puede tener código como datos agregando caracteres que hacen que los códigos sean literales. Entonces '(fun a b c) se convierte en (fun a b c) como una estructura de datos después de la evaluación ya que tiene un ' delante y funciona como si tuviera code(a,b,c) en Python y lo rodeara con comillas como 'code(a,b,c)'. Python lo evaluaría como una cadena y no como un código, ¿verdad? Bien, los lenguajes lisp hacen lo mismo con las estructuras de datos literales. Hay 2 adicionales. quasiquote ` y unquote ,. ¿Te resulta familiar? Bueno, como una asimilación, el quote normal es como cadenas entre comillas simples, donde la cadena es exactamente literal, mientras que quasiquote es como comillas dobles y la comilla es para la interpolación de código, de modo que lo que queda en la estructura es el resultado de esas expresiones. Aquí hay un ejemplo:

`(a b ,(+ 3 4)))
; ==> (a b 7)

Ahora, en idiomas lisp, el lector generalmente convierte esto en el momento de la lectura para que el código que se interpreta nunca vea realmente ', ` o ,. El estándar de esquema no dice cómo debe llamarse, por lo que su implementación está definida, sin embargo, la mayoría de los idiomas usan estos:

''`(a b ,(+ 3 4))
; ==> (quote (quasiquote (a b (unquote (+ 3 4)))))

Solo se evalúa la cita más externa, por lo que en este caso las otras citas que ve en el resultado son datos y no parte del código. Una implementación es libre de mostrar la forma corta al presentar una estructura de datos para que:

'(quote (unquote quote))
; ==> ',quote 
; ==> (quote (unquote quote))

En realidad, es el mismo valor, pero la forma en que lo muestran es una variación si tomas el car, presentaría el símbolo quote ya que realmente es la segunda estructura que es el valor real.

En su código, la expresión (a, (- b 1)) se lee como (a (unqote (- b 1))) y después de la sustracción exitosa se aplicará la función unquote, luego se aplicará la función a resultado. Ninguno de los dos funcionaría, pero dado que los argumentos deben evaluarse antes de la aplicación, se establece el orden, por lo que Scheme se quejará de unquote primero, luego a más tarde si elimina la coma.

6
Sylwester 29 dic. 2016 a las 23:37

Además de la respuesta totalmente correcta anterior: cuando estás aprendiendo a programar, una de las habilidades más importantes es aprender a aislar tus errores eliminando las partes de tu programa que se pueden eliminar sin cambiar el error, para llegar a un programa más pequeño posible que muestra el error. ¡Esto te ahorrará mucho tiempo a largo plazo!

3
John Clements 29 dic. 2016 a las 22:33

Scheme usa espacios en blanco para separar argumentos, no comas (el operador unquote mencionado en el mensaje de error).

1
Scott Hunter 29 dic. 2016 a las 20:13