Articulo de referencia

Sistema de objetos Lisp común

Combinación de métodos estándar en ANSI Common Lisp El Common Lisp Object System (CLOS) es la herramienta para la programación orientada a objetos en ANSI Common Lisp . CLOS es ...

Combinación de métodos estándar en ANSI Common Lisp

El Common Lisp Object System (CLOS) es la herramienta para la programación orientada a objetos en ANSI Common Lisp . CLOS es un sistema de objetos dinámico que difiere radicalmente de las herramientas de POO que se encuentran en lenguajes más estáticos como C++ o Java . CLOS se inspiró en sistemas de objetos Lisp anteriores, como MIT Flavors y CommonLoops , aunque es más general que ambos. Originalmente propuesto como un complemento, CLOS fue adoptado como parte del estándar ANSI para Common Lisp y se ha adaptado a otros dialectos de Lisp como EuLisp o Emacs Lisp . [ 1 ]

Características

Los componentes básicos de CLOS son métodos , clases , instancias de esas clases y funciones genéricas . CLOS proporciona macros para definirlos: defclass, defmethod, y defgeneric. Las instancias se crean con el método make-instance.

Las clases pueden tener múltiples superclases , una lista de ranuras (variables miembro en la terminología de C++/Java) y una metaclase especial . Las ranuras se pueden asignar por clase (todas las instancias de una clase comparten la ranura) o por instancia. Cada ranura tiene un nombre y se puede acceder a su valor mediante ese nombre utilizando la función slot-value. Además, se pueden definir funciones genéricas especiales para escribir o leer valores de ranuras. Cada ranura en una clase CLOS debe tener un nombre único.

CLOS es un sistema de despacho múltiple . Esto significa que los métodos pueden especializarse según uno o todos sus argumentos requeridos. La mayoría de los lenguajes orientados a objetos son de despacho único, lo que significa que los métodos solo se especializan según el primer argumento. Otra característica inusual es que los métodos no "pertenecen" a las clases; las clases no proporcionan un espacio de nombres para funciones o métodos genéricos. Los métodos se definen por separado de las clases y no tienen acceso especial (por ejemplo, "this", "self" o "protected") a las ranuras de la clase.

En CLOS, los métodos se agrupan en funciones genéricas . Una función genérica es un objeto que se puede invocar como una función y que asocia un conjunto de métodos con un nombre y una estructura de argumentos compartidos, cada uno especializado para diferentes argumentos. Dado que Common Lisp proporciona clases que no son de CLOS para estructuras y tipos de datos integrados (números, cadenas, caracteres, símbolos, etc.), el despacho de CLOS también funciona con estas clases. CLOS también admite el despacho sobre objetos individuales (especializadores eql). Por defecto, CLOS no admite el despacho sobre todos los tipos de datos de Common Lisp (por ejemplo, el despacho no funciona para tipos de matrices totalmente especializados ni para tipos introducidos por deftype). Sin embargo, la mayoría de las implementaciones de Common Lisp proporcionan un protocolo de metaobjeto que permite a las funciones genéricas proporcionar especialización y reglas de despacho específicas de la aplicación.

El despacho en CLOS también es diferente al de la mayoría de los lenguajes orientados a objetos:

  1. Dada una lista de argumentos, se determina una lista de métodos aplicables.
  2. Esta lista está ordenada según la especificidad de sus especialistas de parámetros.
  3. Los métodos seleccionados de esta lista se combinan luego en un método efectivo utilizando la combinación de métodos empleada por la función genérica.
  4. A continuación, se llama al método efectivo con los argumentos originales.

Este mecanismo de despacho funciona en tiempo de ejecución. Por lo tanto, agregar o eliminar métodos puede provocar cambios en los métodos efectivos (incluso cuando se llama a la función genérica con los mismos argumentos) en tiempo de ejecución. Cambiar la combinación de métodos también puede dar lugar a diferentes métodos efectivos.

Por ejemplo,

; Declara el prototipo de estructura de argumento común. ( defgeneric f ( x y )); Define una implementación para (f entero y), donde y coincide con todos los tipos. ( defmethod f (( x entero ) y ) 1 )( f 1 2.0 ) => 1; Defina una implementación para (f entero real). ( defmethod f (( x entero ) ( y real )) 2 )( f 1 2.0 ) => 2 ; El despacho cambió en tiempo de ejecución.

Al igual que los sistemas orientados a objetos en la mayoría de los lenguajes dinámicos , CLOS no impone la encapsulación . Se puede acceder a cualquier ranura mediante la función o a través de métodos de accesoslot-value (opcionalmente autogenerados) . Para acceder a ella, es necesario conocer el nombre de la ranura. Los programadores de CL utilizan la funcionalidad de paquetes del lenguaje para declarar qué funciones o estructuras de datos se exportarán.slot-value

Además de los métodos normales ("principales"), también existen :beforelos métodos auxiliares. Los dos primeros se invocan antes o después del método principal, en un orden específico según la jerarquía de clases. Un :aftermétodo auxiliar puede controlar si se ejecuta o no el método principal. Asimismo, el programador puede especificar si se deben llamar todos los métodos principales posibles de la jerarquía de clases o solo el que mejor se ajuste.:around:around

La combinación de métodos estándar proporciona los métodos primario, previo, posterior y de contorno explicados anteriormente. Existen otras combinaciones de métodos con otros tipos de métodos. Se pueden definir nuevas combinaciones de métodos y tipos de métodos (tanto simples como complejos).

CLOS permite la herencia múltiple . Cuando el orden predeterminado de ejecución de los métodos en la herencia múltiple no es correcto, el programador puede resolver los problemas de herencia en diamante especificando el orden de las combinaciones de métodos.

CLOS es dinámico, lo que significa que no solo el contenido, sino también la estructura de sus objetos se pueden modificar en tiempo de ejecución. CLOS admite cambios en las definiciones de clase sobre la marcha (incluso cuando ya existen instancias de la clase en cuestión), así como el cambio de la pertenencia a una clase de una instancia dada mediante el change-classoperador. CLOS también permite agregar, redefinir y eliminar métodos en tiempo de ejecución. El problema del círculo-elipse se resuelve fácilmente en CLOS, y la mayoría de los patrones de diseño de la programación orientada a objetos desaparecen o se simplifican cualitativamente. [ 2 ]

CLOS no es un lenguaje de prototipos : las clases deben definirse antes de que los objetos puedan instanciarse como miembros de esa clase.

Protocolo de metaobjetos

Fuera del estándar ANSI Common Lisp, existe una extensión ampliamente implementada de CLOS llamada Protocolo de Metaobjetos (MOP). El MOP define una interfaz estándar para los fundamentos de la implementación de CLOS, tratando las clases, las descripciones de ranuras, las funciones genéricas y los métodos como instancias de metaclases , y permite la definición de nuevas metaclases y la modificación de todo el comportamiento de CLOS. La flexibilidad del MOP de CLOS anticipa la programación orientada a aspectos , que posteriormente fue desarrollada por algunos de los mismos ingenieros, como Gregor Kiczales . El MOP define el comportamiento de todo el sistema de objetos mediante un conjunto de protocolos. Estos se definen en términos de CLOS. Por lo tanto, es posible crear nuevos sistemas de objetos extendiendo o modificando la funcionalidad CLOS proporcionada. El libro " The Art of the Metaobject Protocol" describe el uso e implementación del MOP de CLOS.

Las distintas implementaciones de Common Lisp tienen un soporte ligeramente diferente para el Protocolo de Meta-Objetos. El proyecto Closer [ 3 ] pretende proporcionar las características que faltan.

Influencias de sistemas de objetos más antiguos basados ​​en Lisp.

Flavors (y su sucesor New Flavors) era el sistema de objetos de la MIT Lisp Machine . Gran parte de los sistemas operativos de Lisp Machine y muchas de sus aplicaciones utilizan Flavors o New Flavors. Flavors introdujo la herencia múltiple y los mixins , entre otras características. Flavors está prácticamente obsoleto, aunque existen implementaciones para Common Lisp. Flavors utilizaba el paradigma de paso de mensajes. New Flavors introdujo las funciones genéricas.

CommonLoops fue el sucesor de LOOPS (de Xerox Interlisp -D). CommonLoops se implementó para Common Lisp. Una implementación portátil llamada Portable CommonLoops (PCL) fue la primera implementación de CLOS. PCL se ha adaptado ampliamente y aún sirve de base para la implementación de CLOS en varias implementaciones de Common Lisp . PCL se implementa principalmente en Common Lisp portátil, con solo algunas partes dependientes del sistema.

CLOS en otros lenguajes de programación

Debido a la potencia y expresividad de CLOS, así como a la disponibilidad histórica de Tiny CLOS (una implementación portátil y simplificada de CLOS escrita por Gregor Kiczales para su uso con Scheme), los sistemas de objetos basados ​​en MOP similares a CLOS se han convertido en la norma de facto en la mayoría de las implementaciones de dialectos de Lisp, además de estar encontrando su camino en las funcionalidades de POO de otros lenguajes :

  • COS, el sistema de objetos C [ 4 ]
  • Dylan
  • Dynace, una implementación (en gran medida) CLOS en C [ 5 ]
  • EIEIO para Emacs Lisp
  • Gauche, Esquema con CLOS
  • GOOPS en GNU Guile
  • ILOS en ISLISP
  • Meroon, un sistema de objetos en Scheme
  • Raku
  • Sagitario, un esquema con CLOS
  • ScmObj, para Scheme
  • SOS para el programa MIT
  • STklos, un esquema con CLOS
  • Estafa en el crimen organizado
  • COOPERATIVAS en el Programa de Pollos
  • VCLOS para Habilidad [ 6 ]
  • Pequeño CLOS [ 7 ]
  • Clases S4 en lenguajes de programación S y R

Lecturas adicionales

  • Bobrow, Daniel G.; Kahn, Kenneth; Kiczales, Gregor ; Masinter, Larry ; Stefik, Mark; Zdybel, Frank (junio de 1986). «CommonLoops: fusión de Lisp y programación orientada a objetos» (PDF) . Actas de la conferencia sobre lenguajes, sistemas y aplicaciones de programación orientada a objetos . OOPSLA '86. págs. 17-29 . doi : 10.1145/28697.28700 . ISBN  978-0-89791-204-4. S2CID 62631315 . Archivado del original (PDF) el 17-08-2022 . Recuperado el 17-03-2022 . 
  • Veitch, Jim (1998). «Historia y descripción de CLOS». En Salus, Peter H. (ed.). Manual de lenguajes de programación, Volumen IV: Lenguajes de programación funcional y lógica (1.ª  ed.). Macmillan Technical Publishing. pp. 107–158 . ISBN  1-57870-011-6.

Referencias

  1. "CLOS es un estándar. Varios proveedores ofrecen CLOS. CLOS (o partes de él) se utiliza para añadir orientación a objetos a otros dialectos de Lisp, como EuLisp o Emacs Lisp." pág. 110 de Veitch 1998
  2. En las diapositivas de Patrones de Diseño en Lenguajes Dinámicos , Peter Norvig presenta sus hallazgos de que 16 de los 23 patrones de diseño tomados de varios libros de texto son "invisibles o más simples" en Dylan o Common Lisp que en C++.
  3. Proyecto Closer: Más cerca de MOP
  4. Deniau, Laurent (12 de marzo de 2010). El sistema de objetos C: Uso de C como lenguaje orientado a objetos de alto nivel (PDF) . arXiv : 1003.2547 . CiteSeerX 10.1.1.763.7946 . Recuperado el 17 de marzo de 2022 . 
  5. Extensión orientada a objetos de Dynace para C
  6. Newton, Jim; Rhodes, Christophe (28 de noviembre de 2008). "Especializadores personalizados en Lisp orientado a objetos" . Journal of Universal Computer Science . 14 (20): 3370– 3388. CiteSeerX 10.1.1.523.2413 . doi : 10.3217/jucs-014-20-3370 . S2CID 12032836. Recuperado el 17 de marzo de 2022 .  
  7. Tiny CLOS, desarrollado por Gregor Kiczales

Literatura