Self (lenguaje de programación)

format_list_bulleted Contenido keyboard_arrow_down
ImprimirCitar

Self es un lenguaje de programación orientado a objetos basado en el concepto de prototipos. Self comenzó como un dialecto de Smalltalk, se tipeaba dinámicamente y utilizaba la compilación justo a tiempo (JIT), así como el enfoque de objetos basado en prototipos: se utilizó por primera vez como un sistema de prueba experimental para el diseño de lenguajes en las décadas de 1980 y 1990.. En 2006, Self todavía se estaba desarrollando como parte del proyecto Klein, que era una máquina virtual Self escrita completamente en Self. La última versión es 2017.1 lanzada en mayo de 2017.

Se introdujeron y mejoraron varias técnicas de compilación justo a tiempo en la investigación de Self, ya que eran necesarias para permitir que un lenguaje orientado a objetos de muy alto nivel funcionara hasta la mitad de la velocidad de C optimizado. Gran parte del desarrollo de Self tomó lugar en Sun Microsystems, y las técnicas que desarrollaron se implementaron más tarde para la máquina virtual HotSpot de Java.

En un momento se implementó una versión de Smalltalk en Self. Debido a que pudo usar el JIT, esto también brindó un rendimiento extremadamente bueno.

Historia

Self fue diseñado principalmente por David Ungar y Randall Smith en 1986 mientras trabajaban en Xerox PARC. Su objetivo era impulsar el estado del arte en la investigación del lenguaje de programación orientado a objetos, una vez que los laboratorios lanzaron Smalltalk-80 y la industria comenzó a tomarlo en serio. Se mudaron a la Universidad de Stanford y continuaron trabajando en el lenguaje, construyendo el primer compilador Self en funcionamiento en 1987. En ese momento, el enfoque cambió para intentar generar un sistema completo para Self, en lugar de solo el lenguaje.

El primer lanzamiento público fue en 1990 y, al año siguiente, el equipo se mudó a Sun Microsystems, donde continuaron trabajando en el lenguaje. Siguieron varios lanzamientos nuevos hasta que quedaron inactivos en gran medida en 1995 con la versión 4.0. La versión 4.3 se lanzó en 2006 y se ejecutó en Mac OS X y Solaris. Un nuevo lanzamiento en 2010, la versión 4.4, ha sido desarrollado por un grupo compuesto por parte del equipo original y programadores independientes y está disponible para Mac OS X y Linux, al igual que todas las versiones siguientes. El seguimiento 4.5 se lanzó en enero de 2014 y, tres años después, se lanzó la versión 2017.1 en mayo de 2017.

El entorno de construcción de la interfaz de usuario de Morphic fue desarrollado originalmente por Randy Smith y John Maloney para el lenguaje de programación Self. Morphic ha sido portado a otros lenguajes de programación notables, incluidos Squeak, JavaScript, Python y Objective-C.

Self también inspiró varios lenguajes basados en sus conceptos. Los más notables, quizás, fueron NewtonScript para Apple Newton y JavaScript utilizado en todos los navegadores modernos. Otros ejemplos incluyen Io, Lisaac y Agora. El sistema de objetos distribuidos de IBM Tivoli Framework, desarrollado en 1990, era, en el nivel más bajo, un sistema de objetos basado en prototipos inspirado en Self.

Lenguajes de programación basados en prototipos

Los lenguajes OO tradicionales basados en clases se basan en una dualidad profundamente arraigada:

  1. Las clases definen las cualidades y comportamientos básicos de los objetos.
  2. Los casos de objetos son manifestaciones particulares de una clase.

Por ejemplo, supongamos que los objetos de la clase Vehículo tienen un nombre y la capacidad de realizar varias acciones, como conducir al trabajo y entregar materiales de construcción. Bob's car es un objeto particular (instancia) de la clase Vehicle, con el nombre "Bob's car". En teoría, uno puede enviar un mensaje al coche de Bob, diciéndole que entregue materiales de construcción.

Este ejemplo muestra uno de los problemas con este enfoque: el automóvil de Bob, que resulta ser un automóvil deportivo, no puede transportar ni entregar materiales de construcción (en ningún sentido significativo), pero esta es una capacidad que los Vehicles están modelados para tener. Un modelo más útil surge del uso de subclases para crear especializaciones de Vehicle; por ejemplo, Coche deportivo y Camión de plataforma. Solo los objetos de la clase Flatbed Truck necesitan proporcionar un mecanismo para entregar materiales de construcción; los coches deportivos, que no son adecuados para ese tipo de trabajo, sólo necesitan conducir rápido. Sin embargo, este modelo más profundo requiere más conocimiento durante el diseño, conocimiento que solo puede salir a la luz cuando surgen problemas.

Este problema es uno de los factores que motivan los prototipos. A menos que se pueda predecir con certeza qué cualidades tendrá un conjunto de objetos y clases en un futuro lejano, no se puede diseñar una jerarquía de clases correctamente. Con demasiada frecuencia, el programa eventualmente necesitaría comportamientos adicionales, y sería necesario rediseñar (o refactorizar) secciones del sistema para dividir los objetos de una manera diferente. La experiencia con los primeros lenguajes OO como Smalltalk mostró que este tipo de problemas surgían una y otra vez. Los sistemas tenderían a crecer hasta cierto punto y luego volverse muy rígidos, ya que las clases básicas muy por debajo del código del programador se volvieron simplemente 'incorrectas'. Sin alguna forma de cambiar fácilmente la clase original, podrían surgir serios problemas.

Los lenguajes dinámicos como Smalltalk permitieron este tipo de cambio a través de métodos bien conocidos en las clases; al cambiar la clase, los objetos basados en ella cambiarían su comportamiento. Sin embargo, tales cambios debían realizarse con mucho cuidado, ya que otros objetos basados en la misma clase podrían estar esperando este "incorrecto" comportamiento: "incorrecto" a menudo depende del contexto. (Esta es una forma del problema de la clase base frágil). Además, en lenguajes como C++, donde las subclases se pueden compilar por separado de las superclases, un cambio en una superclase puede romper los métodos de subclase precompilados. (Esta es otra forma del problema de la clase base frágil, y también una forma del problema de la interfaz binaria frágil).

En Self y otros lenguajes basados en prototipos, se elimina la dualidad entre clases e instancias de objetos.

En lugar de tener una "instancia" de un objeto que se basa en alguna "clase", en Self uno hace una copia de un objeto existente y lo cambia. Entonces, el auto de Bob se crearía haciendo una copia de un "vehículo" y luego agregando el método drive fast, modelando el hecho de que resulta ser un Porsche 911. Los objetos básicos que se usan principalmente para hacer copias se conocen como prototipos. Se afirma que esta técnica simplifica enormemente el dinamismo. Si un objeto existente (o conjunto de objetos) resulta ser un modelo inadecuado, un programador puede simplemente crear un objeto modificado con el comportamiento correcto y usarlo en su lugar. El código que utiliza los objetos existentes no cambia.

Descripción

Los objetos propios son una colección de "ranuras". Las ranuras son métodos de acceso que devuelven valores, y colocar dos puntos después del nombre de una ranura establece el valor. Por ejemplo, para un espacio llamado "nombre",

MyPerson Nombre

devuelve el valor de nombre, y

MyPerson nombre:'foo '

lo establece.

Self, como Smalltalk, usa bloques para el control de flujo y otras funciones. Los métodos son objetos que contienen código además de ranuras (que utilizan para argumentos y valores temporales), y se pueden colocar en una ranura Self como cualquier otro objeto: un número, por ejemplo. La sintaxis sigue siendo la misma en ambos casos.

Tenga en cuenta que en Self no hay distinción entre campos y métodos: todo es un espacio. Dado que acceder a las ranuras a través de mensajes constituye la mayor parte de la sintaxis en Self, muchos mensajes se envían a "self", y el "self" se puede dejar (de ahí el nombre).

Sintaxis básica

La sintaxis para acceder a las ranuras es similar a la de Smalltalk. Hay tres tipos de mensajes disponibles:

no
receiver slot_name
binario
receiver + argument
palabra clave
receiver keyword: arg1 With: arg2

Todos los mensajes devuelven resultados, por lo que el receptor (si está presente) y los argumentos pueden ser el resultado de otros mensajes. Seguir un mensaje por un punto significa que Self descartará el valor devuelto. Por ejemplo:

¡Hola, Mundo! ' impresión.

Esta es la versión Self del programa hello world. La sintaxis ' indica un objeto de cadena literal. Otros literales incluyen números, bloques y objetos generales.

La agrupación se puede forzar usando paréntesis. En ausencia de una agrupación explícita, se considera que los mensajes únicos tienen la prioridad más alta, seguidos de los mensajes binarios (agrupados de izquierda a derecha) y las palabras clave que tienen la prioridad más baja. El uso de palabras clave para la asignación daría lugar a algunos paréntesis adicionales donde las expresiones también tenían mensajes de palabras clave, por lo que para evitar que Self requiera que la primera parte de un selector de mensajes de palabras clave comience con una letra minúscula y las partes posteriores comiencen con una letra mayúscula.

válido: base inferior entre: ligadura inferior + altura Y: base arriba / escala factor.

se puede analizar sin ambigüedades y significa lo mismo que:

válido: ()base inferior)
 entre: ()ligadura inferior) + altura)
 Y: ()base arriba) / ()escala factor)).

En Smalltalk-80, la misma expresión se vería escrita como:

válido := auto base inferior entre: auto ligadura inferior + auto altura y: auto base arriba / auto escala factor.

suponiendo que base, ligature, height y scale no fueran variables de instancia de self</ code> pero eran, de hecho, métodos.

Haciendo nuevos objetos

Considere un ejemplo un poco más complejo:

etiqueta Widget Copia etiqueta: ¡Hola, Mundo! '.

hace una copia del "labelWidget" objeto con el mensaje de copia (sin acceso directo esta vez), luego le envía un mensaje para poner "Hello, World" en la ranura llamada "etiqueta". Ahora a hacer algo con eso:

()escritorio activo Ventana) dibujar: ()etiqueta Widget Copia etiqueta: ¡Hola, Mundo! ').

En este caso, el (desktop activeWindow) se ejecuta primero, devolviendo la ventana activa de la lista de ventanas que conoce el objeto de escritorio. A continuación (léase de interior a exterior, de izquierda a derecha) el código que examinamos anteriormente devuelve el labelWidget. Finalmente, el widget se envía a la ranura de dibujo de la ventana activa.

Delegación

En teoría, cada objeto Self es una entidad independiente. Self no tiene ni clases ni meta-clases. Los cambios a un objeto en particular no afectan a ningún otro, pero en algunos casos es deseable que lo hicieran. Normalmente, un objeto puede comprender solo los mensajes correspondientes a sus ranuras locales, pero al tener una o más ranuras que indiquen objetos principales, un objeto puede delegar cualquier mensaje que no entienda por sí mismo. el objeto padre. Cualquier ranura puede convertirse en un puntero principal agregando un asterisco como sufijo. De esta forma, Self maneja tareas que utilizarían la herencia en lenguajes basados en clases. La delegación también se puede utilizar para implementar funciones como espacios de nombres y alcance léxico.

Por ejemplo, suponga que se define un objeto llamado "cuenta bancaria", que se usa en una aplicación simple de contabilidad. Por lo general, este objeto se crearía con los métodos dentro, tal vez "depósito" y "retirar", y cualquier ranura de datos que necesiten. Este es un prototipo, que solo es especial en la forma en que se usa, ya que también es una cuenta bancaria completamente funcional.

Características

Hacer un clon de este objeto para la cuenta de "Bob" creará un nuevo objeto que comienza exactamente como el prototipo. En este caso, hemos copiado las ranuras, incluidos los métodos y cualquier dato. Sin embargo, una solución más común es crear primero un objeto más simple llamado objeto de características que contiene los elementos que normalmente se asociarían con una clase.

En este ejemplo, la "cuenta bancaria" El objeto no tendría el método de depósito y retiro, pero tendría como padre un objeto que sí lo tuviera. De esta forma, se pueden hacer muchas copias del objeto de la cuenta bancaria, pero aún podemos cambiar el comportamiento de todas ellas cambiando las ranuras en ese objeto raíz.

¿En qué se diferencia esto de una clase tradicional? Bueno, considere el significado de:

# Objeto padre: algunos OtherObject.

Este extracto cambia la "clase" de myObject en tiempo de ejecución cambiando el valor asociado con el 'principal*' slot (el asterisco forma parte del nombre del slot, pero no de los mensajes correspondientes). A diferencia de la herencia o el ámbito léxico, el objeto delegado se puede modificar en tiempo de ejecución.

Agregar ranuras

Los objetos en Self se pueden modificar para incluir ranuras adicionales. Esto se puede hacer usando el entorno de programación gráfica, o con la primitiva '_AddSlots:'. Un primitivo tiene la misma sintaxis que un mensaje de palabra clave normal, pero su nombre comienza con el carácter de subrayado. La primitiva _AddSlots debe evitarse porque es un remanente de implementaciones anteriores. Sin embargo, lo mostraremos en el siguiente ejemplo porque acorta el código.

Un ejemplo anterior fue sobre la refactorización de una clase simple llamada Vehículo para poder diferenciar el comportamiento entre automóviles y camiones. En Self uno lograría esto con algo como esto:

¿Qué?AddSlots: ()Silencio vehículo . ()Silenciopadre* = rasgos clonable) Silencio).

Dado que el receptor de '_AddSlots:' primitivo no está indicado, es "self". En el caso de las expresiones escritas en el indicador, ese es un objeto llamado "vestíbulo". El argumento para '_AddSlots:' es el objeto cuyas ranuras se copiarán en el receptor. En este caso es un objeto literal con exactamente una ranura. El nombre de la tragamonedas es 'vehículo' y su valor es otro objeto literal. El "<-" La notación implica una segunda ranura llamada 'vehículo:' que se puede usar para cambiar el valor de la primera ranura.

El "=" indica una ranura constante, por lo que no hay un 'padre:' correspondiente. El objeto literal que es el valor inicial de 'vehículo' incluye una sola ranura para que pueda comprender los mensajes relacionados con la clonación. Un objeto verdaderamente vacío, indicado como (| |) o más simplemente como (), no puede recibir ningún mensaje.

vehículo ¿Qué?AddSlots: ()Silencio Nombre . Automóvil 'Silencio).

Aquí el receptor es el objeto anterior, que ahora incluirá 'nombre' y 'nombre:' ranuras además de 'padre*'.

¿Qué?AddSlots: ()Silencio deportes Car . vehículo Copia Silencio).deportes Car ¿Qué?AddSlots: ()Silencio driveToWork = ()' 'algunos código, esto es a método' ') Silencio).

Aunque anteriormente 'vehículo' y 'coche deportivo' eran exactamente iguales, ahora este último incluye una nueva ranura con un método que el original no tiene. Los métodos solo se pueden incluir en ranuras constantes.

¿Qué?AddSlots: ()Silencio porche911 . deportes Car Copia Silencio).porche911 nombre:'Bobs Porsche '.

El nuevo objeto 'porsche911' comenzó exactamente como 'sportsCar', pero el último mensaje cambió el valor de su 'nombre' ranura. Tenga en cuenta que ambos todavía tienen exactamente las mismas ranuras aunque uno de ellos tenga un valor diferente.

Entorno

Una característica de Self es que se basa en el mismo tipo de sistema de máquina virtual que usaban los sistemas anteriores de Smalltalk. Es decir, los programas no son entidades independientes como lo son en lenguajes como C, sino que necesitan todo su entorno de memoria para ejecutarse. Esto requiere que las aplicaciones se envíen en fragmentos de memoria guardada conocidos como instantáneas o imágenes. Una desventaja de este enfoque es que las imágenes a veces son grandes y difíciles de manejar; sin embargo, la depuración de una imagen suele ser más sencilla que la depuración de programas tradicionales porque el estado del tiempo de ejecución es más fácil de inspeccionar y modificar. (La diferencia entre el desarrollo basado en fuentes y el basado en imágenes es análoga a la diferencia entre la programación orientada a objetos prototípica y basada en clases).

Además, el entorno se adapta al cambio rápido y continuo de los objetos en el sistema. Refactorización de una "clase" el diseño es tan simple como arrastrar métodos de los ancestros existentes a otros nuevos. Las tareas simples como los métodos de prueba se pueden manejar haciendo una copia, arrastrando el método a la copia y luego cambiándolo. A diferencia de los sistemas tradicionales, solo el objeto modificado tiene el nuevo código y no es necesario reconstruir nada para probarlo. Si el método funciona, simplemente se puede arrastrar de vuelta al antepasado.

Rendimiento

Las máquinas virtuales propias lograron un rendimiento de aproximadamente la mitad de la velocidad de C optimizado en algunos puntos de referencia.

Esto se logró mediante técnicas de compilación justo a tiempo que fueron pioneras y mejoradas en Self research para hacer que un lenguaje de alto nivel funcione tan bien.

Recolección de basura

El recolector de basura para Self utiliza la recolección de basura generacional que separa los objetos por edad. Mediante el uso del sistema de gestión de memoria para registrar escrituras de página, se puede mantener una barrera de escritura. Esta técnica ofrece un rendimiento excelente, aunque después de ejecutarse durante algún tiempo puede producirse una recolección de elementos no utilizados completa, lo que lleva un tiempo considerable.

Optimizaciones

El sistema de tiempo de ejecución aplana selectivamente las estructuras de llamadas. Esto proporciona aceleraciones modestas en sí mismo, pero permite un amplio almacenamiento en caché de información de tipo y múltiples versiones de código para diferentes tipos de personas que llaman. Esto elimina la necesidad de realizar muchas búsquedas de métodos y permite que se inserten instrucciones de ramificación condicional y llamadas codificadas de forma rígida, lo que a menudo brinda un rendimiento similar al de C sin pérdida de generalidad a nivel de idioma, pero en un sistema totalmente recolectado de elementos no utilizados.

Contenido relacionado

DEC Alfa

Telecomunicaciones en Haití

Nortel

Más resultados...
Tamaño del texto:
undoredo
format_boldformat_italicformat_underlinedstrikethrough_ssuperscriptsubscriptlink
save