resueltos principiantes para listas imprimir ejercicios ejemplos ejemplo descargar codigo autolisp lisp common-lisp

principiantes - lisp pdf



Los valores funcionan en Common Lisp. (3)

¿La función de valores en Common Lisp solo es azúcar sintáctica para empaquetar múltiples valores en una lista que se desestructura por el llamador? Lo pregunto porque pensé que Common Lisp admite el retorno de valor múltiple "verdadero" en lugar de devolver una tupla o una lista como en otros idiomas, como Python. Alguien me acaba de decir que es solo azúcar sintáctica, así que me gustaría que alguien me lo explique amablemente. Para intentar comprender el tipo que devuelve la función de valores, escribí (type-of (values 1 2 3)) , y la salida fue BIT . Busqué en la referencia de Common Lisp para eso y no pude encontrarlo mencionado en la sección de tipos de datos. Además, ¿alguien puede compartir algunos recursos que sugieran cómo se implementa la función de valores en Common Lisp? Gracias.


Valores múltiples en CL

El lenguaje Common lisp se describe en el estándar ANSI INCITS 226-1994 (R2004) y tiene muchas implementaciones . Cada uno puede implementar múltiples valores como le parezca, y se les permite, por supuesto, hacer una lista para ellos (de hecho, la capa de compatibilidad de Emacs Lisp para CL hace precisamente eso , pero no es una Implementación de Common Lisp).

Propósito

Sin embargo, la intención de este servicio es permitir pasar (al menos algunos) valores múltiples sin considerar (es decir, sin asignar memoria de heap ) y todas las implementaciones de CL que conozco hacen eso. En este sentido, la facilidad de valores múltiples es una optimización .

Por supuesto, la implementación de esta característica puede ser muy diferente para diferentes plataformas y escenarios. Por ejemplo, los primeros (por ejemplo, 20 - requeridos por el estándar ) se almacenan en un vector estático de subprocesos locales, los siguientes (1000?) Se asignan en la pila, y el resto (si es necesario) se asignan en la pila. el montón como un vector o lista.

Uso

Por ejemplo, la función floor devuelve dos valores. Si tú escribes

(setq a (floor 10 3))

solo captura el primero y descarta el segundo, necesita escribir

(setf (values q r) (floor 10 3))

Para capturar ambos valores. Esto es similar a lo que otros idiomas pueden expresar como

q,r = floor(10,3)

usando tuples , excepto que CL no asigna memoria para pasar (solo unos pocos) valores múltiples, y los otros idiomas a menudo lo hacen.

IOW, uno puede pensar en múltiples valores como una estructura efímera.

Tenga en cuenta que CL puede convertir varios valores a listas:

(destructuring-bind (q r) (multiple-value-list (floor 10 3)) ; use q & r here ...)

En lugar de lo más eficiente y conciso.

(multiple-value-bind (q r) (floor 10 3) ; use q & r here ...)

MV y tipo

CL no tiene un tipo especial para el "objeto de valor múltiple" exactamente porque no asigna un objeto separado para pasar alrededor de varios valores. En este sentido, de hecho, se puede afirmar que los values son azúcar sintáctica.

Sin embargo, en CL se puede declarar que un tipo de función devuelve múltiples valores :

(declaim (ftype (real &optional real) (values real real)) floor)

Esto significa que floor devuelve dos valores, ambos s real (en lugar de devolver un valor de tipo (values real real) ), es decir, en este caso, se puede reclamar un abuso de notación.

Tu caso

En su caso específico, type-of es una función ordinaria (es decir, no una macro u operador especial). Se lo pasa un solo objeto, 1, porque, a menos que esté usando multiple-value-bind y amigos, solo se usa el primer valor, por lo que

(type-of (values 1 2 3))

es idéntico a

(type-of 1)

y el tipo de 1 es bit .

PS: valores de retorno de control

Un uso de los values es controlar los valores de retorno de una función. Normalmente, los valores de retorno de una función CL son los de la última forma. A veces no es deseable, por ejemplo, la última forma devuelve varios valores y desea que su función devuelva un valor (o ninguno, como el void en C ):

(defun 2values (x y) (floor y x)) (defun 1value (x y) (values (floor y x))) (defun no-values (x) (print x) (values))


La función de values no es solo azúcar sintáctica para hacer una lista para que la persona que llama se destruya.

Por un lado, si la persona que llama espera un solo valor, solo obtendrá un valor (el primero), no una lista, de un formulario que devuelve múltiples valores. Ya que type-of toma solo un valor como argumento, le da el tipo del primer valor, 1. 1 es de tipo BIT .

Cada implementación de Common Lisp es libre de seguir su propia estrategia para implementar múltiples valores. Aprendí mucho de lo que Frode Fjeld escribió sobre cómo su implementación, Movitz, la maneja en la plataforma de desarrollo de Movitz , sección 2.5.


Si realiza una implementación de CL, puede implementarla con listas siempre que se ajuste a la especificación. Necesita manejar un valor específico y necesita alguna forma de etiquetar cero, 2..n valores y las otras funciones deben comprender que el formato y la impresión se pueden hacer para mostrarlo de la misma manera que en otras marcas.

Los values más probables y sus funciones hermanas son una optimización en la que las implementaciones usan la pila en lugar de convertir los valores en una estructura de lista para desestructurarlos en el siguiente nivel. En los tiempos antiguos en los que no debía desperdiciarse la memoria RAM y la CPU, era muy importante, pero dudo que note problemas reales si utiliza hoy en día la destructuring-bind lugar de la destructuring-bind de multiple-value-bind .

Common Lisp se diferencia mucho de Scheme en la dirección positiva en la que puede realizar una función, por ejemplo. floor donde en sus cálculos termina con el resto, además del cociente, devuelve todos los valores al mismo tiempo, pero puede usarlo como si solo hubiera devuelto el primer valor. Realmente extraño eso a veces cuando escribo Scheme, ya que exige que tengas una call-with-values que sea similar a una call-with-values multiple-value-call o un azúcar sintáctico como let-values para manejar todos los valores devueltos que nuevamente te hacen terminar con tres. Versiones en caso de que solo necesites uno de los valores.