williamson the ritual plataformas night moon jail curse county bloodstained scheme racket evaluation quote

scheme - moon - bloodstained: ritual of the night plataformas



¿Cuál es la diferencia entre quote y list? (1)

TL; DR: son diferentes; use la list cuando tenga dudas.

Una regla general: use la list siempre que desee que se evalúen los argumentos; quote "distribuye" sobre sus argumentos, por lo que ''(+ 1 2) es como (list ''+ ''1 ''2) . Terminarás con un símbolo en tu lista, no una función.

Una mirada en profundidad a la list y quote

En Scheme and Racket, quote y list son cosas completamente diferentes , pero dado que ambos se pueden usar para producir listas, la confusión es común y comprensible. Hay una diferencia increíblemente importante entre ellos: la list es una función antigua simple, mientras que la quote (incluso sin la sintaxis especial) es una forma especial . Es decir, la list se puede implementar en un esquema simple, pero la quote no se puede implementar.

La función de list

La función de list es en realidad la más simple de las dos, así que comencemos allí. Es una función que toma cualquier número de argumentos y los recoge en una lista.

> (list 1 2 3) (1 2 3)

Este ejemplo anterior puede ser confuso porque el resultado se imprime como una s-expresión entre quote , y es cierto, en este caso, las dos sintaxis son equivalentes. Pero si nos volvemos un poco más complicados, verá que es diferente:

> (list 1 (+ 1 1) (+ 1 1 1)) (1 2 3) > ''(1 (+ 1 1) (+ 1 1 1)) (1 (+ 1 1) (+ 1 1 1))

¿Qué está pasando en el ejemplo de la quote ? Bueno, discutiremos eso en un momento, pero primero, eche un vistazo a la list . Es solo una función ordinaria, por lo que sigue la semántica de evaluación de Scheme estándar: evalúa cada uno de sus argumentos antes de pasarlos a la función. Esto significa que expresiones como (+ 1 1) se reducirán a 2 antes de que se recopilen en la lista.

Este comportamiento también es visible al suministrar variables a la función de lista:

> (define x 42) > (list x) (42) > ''(x) (x)

Con la list , la x se evalúa antes de pasar a la list . Con quote , las cosas son más complicadas.

Finalmente, debido a que list es solo una función, se puede usar como cualquier otra función, incluso en formas de orden superior. Por ejemplo, se puede pasar a la función de map y funcionará adecuadamente:

> (map list ''(1 2 3) ''(4 5 6)) ((1 4) (2 5) (3 6))

El formulario de quote

La cita, a diferencia de la list , es una parte especial de Lisps. El formulario de quote es especial en parte porque tiene una abreviatura de lector especial '' , pero también es especial incluso sin eso. A diferencia de la list , la quote no es una función y, por lo tanto, no necesita comportarse como tal, tiene sus propias reglas.

Una breve discusión del código fuente de Lisp

En Lisp, de los cuales Scheme y Racket son derivados, todo el código está hecho de estructuras de datos ordinarias. Por ejemplo, considere la siguiente expresión:

(+ 1 2)

Esa expresión es en realidad una lista , y tiene tres elementos:

  • el símbolo +
  • el numero 1
  • el numero 2

Todos estos valores son valores normales que el programador puede crear. Es realmente fácil crear el valor 1 porque se evalúa a sí mismo: solo escribe 1 . Pero los símbolos y las listas son más difíciles: por defecto, ¡un símbolo en el código fuente realiza una búsqueda variable! Es decir, los símbolos no se autoevalúan :

> 1 1 > a a: undefined cannot reference undefined identifier

Sin embargo, los símbolos son básicamente cadenas y, de hecho, podemos convertirlos entre ellos:

> (string->symbol "a") a

¡Las listas hacen incluso más que símbolos, porque por defecto, una lista en el código fuente llama a una función! Hacer (+ 1 2) mira el primer elemento de la lista, el símbolo + , busca la función asociada a él y lo invoca con el resto de los elementos de la lista.

A veces, sin embargo, es posible que desee deshabilitar este comportamiento "especial". Es posible que desee obtener la lista u obtener el símbolo sin que se evalúe. Para hacer esto, puede usar quote .

El significado de la cita

Con todo esto en mente, es bastante obvio lo que hace la quote : simplemente "desactiva" el comportamiento de evaluación especial para la expresión que envuelve. Por ejemplo, considere quote un símbolo:

> (quote a) a

Del mismo modo, considere quote una lista:

> (quote (a b c)) (a b c)

No importa lo que quote , siempre, siempre lo escupirá. Ni mas ni menos. Eso significa que si le da una lista, ninguna de las subexpresiones será evaluada, ¡no espere que lo sean! Si necesita una evaluación de algún tipo, use la list .

Ahora, uno podría preguntarse: ¿qué sucede si quote algo que no sea un símbolo o una lista? Bueno, la respuesta es ... ¡nada! Solo lo recuperas.

> (quote 1) 1 > (quote "abcd") "abcd"

Esto tiene sentido, ya que la quote todavía solo escupe exactamente lo que le das. Esta es la razón por la cual los "literales", como los números y las cadenas, a veces se denominan "autocomillas" en el lenguaje Lisp.

Una cosa más: ¿qué sucede si quote una expresión que contiene quote ? Es decir, ¿qué pasa si usted " quote dos quote "?

> (quote (quote 3)) ''3

¿Que paso ahi? Bueno, recuerde que '' realidad es solo una abreviatura directa de quote , ¡así que no pasó nada especial! De hecho, si su Esquema tiene una forma de deshabilitar las abreviaturas al imprimir, se verá así:

> (quote (quote 3)) (quote 3)

No se deje engañar por la quote es especial: al igual que (quote (+ 1)) , el resultado aquí es simplemente una lista antigua. De hecho, podemos sacar el primer elemento de la lista: ¿puedes adivinar cuál será?

> (car (quote (quote 3))) quote

Si adivinaste 3 , estás equivocado. Recuerde, quote deshabilita toda evaluación , y una expresión que contiene un símbolo de quote sigue siendo solo una lista simple. Juega con esto en el REPL hasta que te sientas cómodo con él.

> (quote (quote (quote 3))) ''''3 (quote (1 2 (quote 3))) (1 2 ''3)

La cita es increíblemente simple, pero puede resultar muy compleja debido a que tiende a desafiar nuestra comprensión del modelo de evaluación tradicional. De hecho, es confuso debido a lo simple que es: no hay casos especiales, no hay reglas. Simplemente devuelve exactamente lo que le da, exactamente como se indica (de ahí el nombre "cita").

Apéndice A: Cuasiquotación

Entonces, si la cita inhabilita por completo la evaluación, ¿para qué sirve? Bueno, aparte de hacer listas de cadenas, símbolos o números que se conocen con anticipación, no mucho. Afortunadamente, el concepto de cuasiquotación proporciona una forma de salir de la cita y volver a la evaluación ordinaria.

Los conceptos básicos son súper simples: en lugar de usar quote , use quasiquote . Normalmente, esto funciona exactamente como una quote en todos los sentidos:

> (quasiquote 3) 3 > (quasiquote x) x > (quasiquote ((a b) (c d))) ((a b) (c d))

Lo que hace que la quasiquote sea ​​especial es que reconoce un símbolo especial, unquote . Dondequiera que aparezca una unquote en la lista, entonces se reemplaza por la expresión arbitraria que contiene:

> (quasiquote (1 2 (+ 1 2))) (1 2 (+ 1 2)) > (quasiquote (1 2 (unquote (+ 1 2)))) (1 2 3)

Esto le permite usar quasiquote para construir plantillas de tipo que tengan "agujeros" para rellenar con unquote . Esto significa que es posible incluir los valores de las variables dentro de las listas citadas:

> (define x 42) > (quasiquote (x is: (unquote x))) (x is: 42)

Por supuesto, usar quasiquote y unquote es bastante detallado, por lo que tienen abreviaturas propias, al igual que '' . Específicamente, quasiquote es ` (retroceso) y sin unquote es (coma). Con esas abreviaturas, el ejemplo anterior es mucho más apetecible.

> `(x is: ,x) (x is: 42)

Un último punto: la cuasiquota en realidad se puede implementar en Racket usando una macro bastante peluda, y lo es. Se expande a usos de list , cons y, por supuesto, quote .

Apéndice B: Implementación de list y quote en Esquema

La implementación de la list es súper simple debido a cómo funciona la sintaxis de "argumento de descanso". Esto es todo lo que necesitas:

(define (list . args) args)

¡Eso es!

En contraste, la quote es mucho más difícil, de hecho, ¡es imposible! Parecería totalmente factible, ya que la idea de deshabilitar la evaluación se parece mucho a las macros. Sin embargo, un intento ingenuo revela el problema:

(define fake-quote (syntax-rules () ((_ arg) arg)))

Simplemente tomamos arg y lo volvemos a escupir ... pero esto no funciona. Por qué no? Bueno, se evaluará el resultado de nuestra macro, por lo que todo es en vano. Es posible que podamos expandirnos a algo así como una quote expandiéndonos a (list ...) y citando recursivamente los elementos, así:

(define impostor-quote (syntax-rules () ((_ (a . b)) (cons (impostor-quote a) (impostor-quote b))) ((_ (e ...)) (list (impostor-quote e) ...)) ((_ x) x)))

Sin embargo, desafortunadamente, sin macros de procedimiento, no podemos manejar símbolos sin quote . Podríamos acercarnos usando syntax-case , pero incluso así, solo estaríamos emulando el comportamiento de la quote , no replicando.

Apéndice C: Convenciones de impresión de raquetas

Al probar los ejemplos en esta respuesta en Racket, es posible que no se impriman como cabría esperar. A menudo, pueden imprimir con un encabezado '' , como en este ejemplo:

> (list 1 2 3) ''(1 2 3)

Esto se debe a que Racket, de forma predeterminada, imprime los resultados como expresiones cuando es posible. Es decir, debe poder escribir el resultado en REPL y recuperar el mismo valor. Personalmente, considero que este comportamiento es agradable, pero puede ser confuso al tratar de comprender la cita, por lo que si desea desactivarlo, llame (print-as-expression #f) o cambie el estilo de impresión a "escribir" en DrRacket menú de idiomas

Sé que puedes usar '' (también conocido como quote ) para crear una lista, y lo uso todo el tiempo, así:

> (car ''(1 2 3)) 1

Pero no siempre funciona como esperaba. Por ejemplo, intenté crear una lista de funciones, como esta, pero no funcionó:

> (define math-fns ''(+ - * /)) > (map (lambda (fn) (fn 1)) math-fns) application: not a procedure; expected a procedure that can be applied to arguments given: ''+

Cuando uso la list , funciona:

> (define math-fns (list + - * /)) > (map (lambda (fn) (fn 1)) math-fns) ''(1 -1 1 1)

¿Por qué? Pensé '' era solo una taquigrafía conveniente, entonces, ¿por qué es diferente el comportamiento?