initialize - structs in java
¿Cuál es el equivalente idiomático de C structs en Lisp? (6)
En los lenguajes de tipo C, hay un fuerte énfasis en las estructuras / registros y objetos desde el principio y en cada libro de introducción. Luego, sus sistemas completos están diseñados para gestionar tales estructuras, sus relaciones mutuas y su herencia.
En la documentación de Lisp, usualmente puede encontrar 1-2 páginas acerca de cómo Lisp "también" tiene un desestructurado, un ejemplo simple, y eso es usualmente. Además, la anidación de estructuras nunca se menciona en absoluto.
Para alguien que viene de un fondo en C, primero parece que organizar diferentes tipos de datos jerárquicamente no es el método preferido en Lisp, pero aparte de CLOS, que es un sistema de objetos completo y muy complicado si solo quieres estructuras, y aparte de abarrotar todo en las listas, no hay una forma aparente de transferir su conocimiento de C struct.
¿Cuál es la forma idiomática de Lisp de organizar jerárquicamente los datos que más se parecen a las estructuras C?
-
Creo que la respuesta resumida a mi pregunta sería: para propósitos de aprendizaje para principiantes, se pueden usar desestructuraciones y / o errores, aunque se pueden usar "características heredadas", ya que se asemejan más a las estructuras de C, pero que han sido superadas en mayor medida por las más Defclass / CLOS flexible, que es lo que la mayoría de los programas Lisp usan hoy en día.
Esta fue mi primera pregunta sobre SO, así que gracias a todos por su tiempo al responderla.
¿Por qué no usar tablas hash? Cada miembro de la estructura puede ser una clave en una tabla hash.
Creo que el equivalente idiomático de una estructura C es no tener que almacenar los datos en las estructuras en primer lugar. Yo diría que al menos el 50% del código de estilo C que he transferido a Lisp, en lugar de almacenar los datos en una estructura elaborada, simplemente calculo qué es lo que quiero calcular. C necesita estructuras para almacenar todo temporalmente porque sus expresiones son muy débiles.
Si usted es un ejemplo específico de algún código de estilo C, estoy seguro de que podríamos demostrar una forma idiomática de implementarlo en Lisp.
Más allá de eso, recuerde que las s-exp de Lisp son datos jerárquicos. Una expresión if
en Lisp, por ejemplo, es en sí misma datos jerárquicos.
Los ejemplos con defstruct
son cortos y simples porque no hay mucho que decir sobre ellos. Las struct
de C son complicadas:
- gestión de la memoria
Disposición de memoria complicada debido a uniones, estructuras anidadas en línea En C, las
structs
también se utilizan para otros fines:para acceder a la memoria
- debido a la falta de polimorfismo o capacidad de pasar un valor de ''cualquier tipo'': es idiomático pasar un
void*
- Debido a la incapacidad de tener otros medios para pasar datos; Por ejemplo, en Lisp puede pasar un cierre que tiene los datos necesarios.
- Debido a la falta de convenciones de llamadas avanzadas; Algunas funciones aceptan sus argumentos dentro de estructuras.
En Common Lisp, defstruct
es aproximadamente equivalente a la class
Java / C #: herencia simple, ranuras fijas, se pueden usar como especificadores en defmethod
s (análogo a virtual
métodos virtual
). Las estructuras son perfectamente utilizables para estructuras de datos anidadas.
Los programas Lisp tienden a no usar estructuras profundamente anidadas (el código fuente de Lisp es la excepción principal) debido a que a menudo son posibles representaciones más simples.
Utilice CLOS. No es complicado.
De lo contrario usar estructuras.
Si tiene una pregunta específica sobre cómo usarlos, solo pregunte.
(defclass point ()
((x :type number)
(y :type number)))
(defclass rectangle ()
((p1 :type point)
(p2 :type point)
(color :type color)))
Cosas como esas eventualmente llevan a interfaces como Rectángulos en CLIM (el Administrador de Interfaz de Common Lisp).
Historia
Para ampliarlo un poco: las "estructuras" históricamente se han utilizado en algunas situaciones de bajo nivel. Las estructuras tienen una herencia única y el acceso a la ranura es "rápido". Algunos dialectos de Lisp tienen más estructuras que lo que ofrece Common Lisp. Luego, desde mediados de los años 70, se han desarrollado diversas formas de representaciones orientadas a objetos para Lisp. La mayoría de la representación de objetos estructurados se movió desde estructuras a algún tipo de extensión Lisp orientada a objetos. Los populares en la década de los 80 fueron sistemas basados en clases como Flavors, LOOPS y otros. Los sistemas basados en marcos o prototipos como KEE Units u Object Lisp también fueron populares. El primer Common Lisp de Macintosh utilizó Object Lisp para todas sus instalaciones de IU e IO. La máquina MIT Lisp usaba sabores básicamente en todas partes. A partir de mediados de los 80 se desarrolló ANSI CL. Un sistema OO común fue desarrollado especialmente para Common Lisp: CLOS. Se basó en Sabores y Bucles. Durante ese tiempo, en su mayoría no se hizo nada para mejorar realmente las estructuras, además de los implementadores que encuentran maneras de mejorar la implementación y proporcionar una integración CLOS superficial. Por ejemplo, las estructuras no proporcionan ningún paquete de datos. Si hay dos ranuras de contenido de 4 bits, no hay forma de indicar a Common Lisp que codifique ambas ranuras en una sola región de memoria de 8 bits.
Como ejemplo, puede ver en el Manual de la máquina Lisp, capítulo sobre estructuras (PDF) , que tenía estructuras mucho más complejas de las que proporciona Common Lisp. Parte de eso ya estaba presente en Maclisp en los años 70: DEFSTRUCT en el manual de Maclisp .
CLOS, el sistema de objetos Common Lisp
La mayoría de la gente estaría de acuerdo en que CLOS es un buen diseño. A veces conduce a un código ''más grande'', principalmente porque los identificadores pueden alargarse. Pero hay un código CLOS, como el del libro AMOP, que está muy bien escrito y muestra cómo se debe usar.
Con el tiempo, los implementadores tuvieron que enfrentar el desafío que los desarrolladores querían usar CLOS, pero también querían tener la "velocidad" de las estructuras. Lo que es aún más una tarea con el CLOS ''completo'', que incluye el protocolo de objeto Meta (MOP) casi estándar para CLOS. Así que hay algunos trucos que proporcionan los implementadores. Durante la década de los 80, algunos programas usaron un interruptor, por lo que se podía compilar usando estructuras o usando CLOS - CLX (la interfaz de Common Lisp X11 de bajo nivel fue un ejemplo). La razón: en algunas computadoras e implementaciones, CLOS era mucho más lento que las estructuras. Hoy en día sería inusual proporcionar un cambio de compilación de este tipo.
Si observo hoy una buena implementación de Common Lisp, espero que use CLOS en casi todas partes. STREAMs son clases de CLOS. Las CONDICIONES son clases de CLOS. El kit de herramientas GUI utiliza clases CLOS. El editor utiliza CLOS. Incluso podría integrar clases extranjeras (por ejemplo, clases de Objective C) en CLOS.
En cualquier implementación de Common Lisp que no sea de juguete, CLOS será la herramienta para proporcionar datos estructurados, comportamiento genérico y un montón de otras cosas.
Como se mencionó en algunas de las otras respuestas, en algunos lugares es posible que no se necesite CLOS.
Common Lisp puede devolver más de un valor desde una función:
(defun calculate-coordinates (ship)
(move-forward ship)
(values (ship-x ship)
(ship-y ship)))
Uno puede almacenar datos en cierres:
(defun create-distance-function (ship x y)
(lambda ()
(point-distance (ship-x ship) (ship-y ship) x y)))
Para la configuración se puede utilizar algún tipo de listas:
(defship ms-germany :initial-x 0 :initial-y 0)
Puedes apostar a que yo implementaría el modelo de nave en CLOS.
Una lección de escribir y mantener el software CLOS es que debe diseñarse con cuidado y CLOS es tan poderoso que se puede crear software realmente complejo con él, una complejidad que a menudo no es una buena idea. Refactorizar y simplificar! Afortunadamente, para muchas tareas, las instalaciones básicas de CLOS son suficientes: DEFCLASS, DEFMETHOD y MAKE-INSTANCE.
Punteros a las introducciones de CLOS
Para empezar, Richard P. Gabriel tiene sus documentos CLOS para descargar.
Ver también:
- http://cl-cookbook.sourceforge.net/clos-tutorial/index.html
- http://www.aiai.ed.ac.uk/~jeff/clos-guide.html
- Capítulo de libro de Practical Common Lisp, reorientación de objetos, clases
- Capítulo de libro de Practical Common Lisp, reorientación de objetos, funciones genéricas
- Guía para principiantes de C ++ Coder al estilo OO de Lisp
- Libro: El Arte del Protocolo de Metaobjetos . Según un tipo llamado Alan Kay, el libro de informática más importante en una década, desafortunadamente escrito para Lispers ;-). El libro explica cómo modificar o ampliar el CLOS. También incluye una implementación simple de CLOS como fuente. Para los usuarios normales, este libro no es realmente necesario, pero el estilo de programación es el de los verdaderos expertos de Lisp.
(defclass point ()
( x y z))
(defun distance-from-origin (point)
(with-slots (x y z)
point
(sqrt (+ (* x x) (* y y) (* z z)))))
Creo que esto es algo de lo que estaba buscando, se puede encontrar aquí:
http://cl-cookbook.sourceforge.net/clos-tutorial/index.html y