En informática , un lenguaje de programación dinámico es una clase de lenguajes de programación de alto nivel , que en tiempo de ejecución ejecutan muchos comportamientos de programación comunes que los lenguajes de programación estáticos realizan durante la compilación . Estos comportamientos podrían incluir una extensión del programa, agregando nuevo código , extendiendo objetos y definiciones, o modificando el sistema de tipos.. Aunque se pueden emular comportamientos similares en casi cualquier idioma, con diversos grados de dificultad, complejidad y costos de rendimiento, los lenguajes dinámicos proporcionan herramientas directas para hacer uso de ellos. Muchas de estas características se implementaron por primera vez como características nativas en el lenguaje de programación Lisp .
La mayoría de los lenguajes dinámicos también se escriben dinámicamente , pero no todos. Los lenguajes dinámicos se denominan frecuentemente (pero no siempre) lenguajes de secuencias de comandos , aunque ese término en su sentido más estricto se refiere a lenguajes específicos de un entorno de tiempo de ejecución determinado.
Implementación
Eval
Algunos lenguajes dinámicos ofrecen una función de evaluación . Esta función toma un parámetro de cadena que contiene código en el idioma y lo ejecuta. Si este código representa una expresión, se devuelve el valor resultante. Sin embargo, Erik Meijer y Peter Drayton sugieren que los programadores "usan eval como un sustituto de los pobres para las funciones de orden superior ". [1]
Alteración del tiempo de ejecución del objeto
Normalmente, un sistema de tipo u objeto se puede modificar durante el tiempo de ejecución en un lenguaje dinámico. Esto puede significar generar nuevos objetos a partir de una definición en tiempo de ejecución o basados en combinaciones de tipos u objetos existentes. Esto también puede referirse a cambiar la herencia o el árbol de tipos y, por lo tanto, alterar la forma en que se comportan los tipos existentes (especialmente con respecto a la invocación de métodos ).
Reflexión
La reflexión es común en muchos lenguajes dinámicos y, por lo general, implica el análisis de los tipos y metadatos de datos genéricos o polimórficos . Sin embargo, también puede incluir la evaluación completa y la modificación del código de un programa como datos, como las características que proporciona Lisp para analizar expresiones-S .
Macros
Un número limitado de lenguajes de programación dinámica proporcionan características que combinan la introspección de código (la capacidad de examinar clases, funciones y palabras clave para saber qué son, qué hacen y qué saben) y eval en una característica llamada macros . La mayoría de los programadores de hoy que conocen el término macro los han encontrado en C o C ++ , donde son una característica estática que se construye en un pequeño subconjunto del lenguaje y solo son capaces de sustituir cadenas en el texto del programa. En los lenguajes dinámicos, sin embargo, brindan acceso al funcionamiento interno del compilador y acceso completo al intérprete, la máquina virtual o el tiempo de ejecución, lo que permite la definición de construcciones similares al lenguaje que pueden optimizar el código o modificar la sintaxis o gramática del lenguaje. idioma.
Ensamblador , C , C ++ , Java temprano y Fortran generalmente no encajan en esta categoría. [ aclaración necesaria ]
Código de ejemplo
Los siguientes ejemplos muestran características dinámicas usando el lenguaje Common Lisp y su Common Lisp Object System (CLOS).
Cálculo de código en tiempo de ejecución y enlace tardío
El ejemplo muestra cómo se puede modificar una función en tiempo de ejecución a partir del código fuente calculado
; el código fuente se almacena como datos en una variable CL-USER > ( defparameter * best-guess-formula * ' ( lambda ( x ) ( * x x 2.5 ))) * BEST-GUESS-FORMULA *; se crea una función a partir del código y se compila en tiempo de ejecución, la función está disponible con el nombre best-guess CL-USER > ( compile 'best-guess * best-guess-formula * ) # ón> 15 40600152F4>; la función se puede llamar CL-USER > ( mejor estimación 10.3 ) 265.225; el código fuente podría mejorarse en tiempo de ejecución CL-USER > ( setf * best-guess-formula * ` ( lambda ( x ) , ( list 'sqrt ( third * best-guess-formula * )))) ( LAMBDA ( X ) ( SQRT ( * X X 2.5 ))); se está compilando una nueva versión de la función CL-USER > ( compile 'best-guess * best-guess-formula * ) # ón> 16 406000085C>; la próxima llamada llamará a la nueva función, una característica de CL-USER de enlace tardío > ( mejor estimación 10.3 ) 16.28573
Alteración del tiempo de ejecución del objeto
Este ejemplo muestra cómo se puede cambiar una instancia existente para incluir una nueva ranura cuando cambia su clase y que un método existente se puede reemplazar con una nueva versión.
; una clase de persona. La persona tiene un nombre. CL-USER > ( defclass person () (( name : initarg : name ))) # PERSON 4020081FB3>; un método de impresión personalizado para los objetos de clase person CL-USER > ( defmethod print-object (( p person ) stream ) ( print-unreadable-object ( p stream : type t ) ( format stream "~ a" ( slot-value p 'nombre )))) # < OBJETO DE IMPRESIÓN DEL MÉTODO ESTÁNDAR NIL ( PERSONA T ) 4020066E5B>; un ejemplo person instancia CL-USER > ( setf * person-1 * ( make-instance 'person : name "Eva Luator" )) # Eva Luator>; la persona de la clase obtiene un segundo puesto. Luego tiene el nombre y la edad de las tragamonedas. CL-USER > ( defclass person () (( name : initarg : name ) ( age : initarg : age : initform : unknown ))) # < PERSONA DE CLASE ESTÁNDAR 4220333E23>; actualizando el método para imprimir el objeto CL-USER > ( defmethod print-object (( p person ) stream ) ( print-unreadable-object ( p stream : type t ) ( format stream "~ a age: ~" ( slot-value p 'nombre ) ( valor de ranura p ' edad )))) # étodo> IMPRESIÓN-OBJETO NIL ( PERSONA T ) 402022ADE3>; el objeto existente ahora ha cambiado, tiene una ranura adicional y un nuevo método de impresión CL-USER > * person-1 * # Eva Luator age: UNKNOWN>; podemos establecer el intervalo de nueva era de la instancia CL-USER > ( setf ( valor-intervalo * persona-1 * 'edad ) 25 ) 25; el objeto ha sido actualizado CL-USER > * person-1 * # Eva Luator edad: 25>
Ensamblaje de código en tiempo de ejecución basado en la clase de instancias
En el siguiente ejemplo, la persona de la clase obtiene una nueva superclase. El método de impresión se redefine de modo que reúna varios métodos en el método efectivo. El método efectivo se ensambla según la clase del argumento y los métodos disponibles y aplicables en tiempo de ejecución.
; la persona de clase CL-USER > ( defclass person () (( nombre : initarg : nombre ))) # < PERSONA DE CLASE ESTÁNDAR 4220333E23>; una persona simplemente imprime su nombre CL-USER > ( defmethod print-object (( p person ) stream ) ( print-unreadable-object ( p stream : type t ) ( format stream "~ a" ( slot-value p 'name ) ))) # < OBJETO DE IMPRESIÓN DEL MÉTODO ESTÁNDAR NIL ( PERSONA T ) 40200605AB>; una instancia de persona CL-USER > ( defparameter * person-1 * ( make-instance 'person : name "Eva Luator" )) * PERSON-1 *; mostrando una instancia de persona CL-USER > * person-1 * # Eva Luator>; ahora redefiniendo el método de impresión para que sea extensible ; el método around crea el contexto para el método de impresión y llama al siguiente método CL-USER > ( defmethod print-object : around (( p person ) stream ) ( print-unreadable-object ( p stream : type t ) ( call- siguiente-método ))) # étodo> IMPRESIÓN-OBJETO ( : ALREDEDOR ) ( PERSONA T ) 4020263743>; el método primario imprime el nombre CL-USER > ( defmethod print-object (( p person ) stream ) ( format stream "~ a" ( slot-value p 'name ))) # PRINT-OBJECT NIL ( PERSON T ) 40202646BB>; una nueva clase id-mixin proporciona un ID CL-USER > ( defclass id-mixin () (( id : initarg : id ))) # ID-MIXIN 422034A7AB>; el método de impresión simplemente imprime el valor de la ranura de identificación CL-USER > ( defmethod print-object : after (( object id-mixin ) stream ) ( format stream "ID: ~ a" ( slot-value object 'id )) # < OBJETO DE IMPRESIÓN DEL MÉTODO ESTÁNDAR ( : DESPUÉS ) ( ID-MIXIN T ) 4020278E33>; ahora redefinimos la persona de la clase para incluir el mixin id-mixin CL-USER 241 > ( defclass person ( id-mixin ) (( name : initarg : name ))) # PERSON 4220333E23>; la instancia existente * person-1 * ahora tiene una nueva ranura y la configuramos en 42 CL-USER 242 > ( setf ( slot-value * person-1 * 'id ) 42 ) 42; mostrando el objeto de nuevo. La función print-object ahora tiene un método efectivo, que llama a tres métodos: un método around, el método principal y el método after. CL-USER 243 > * person-1 * # Eva Luator ID: 42>
Ejemplos de
Los lenguajes de programación dinámica populares incluyen JavaScript , Python , Ruby , PHP , Lua y Perl . Los siguientes se consideran generalmente lenguajes dinámicos:
- ActionScript
- BeanShell [2]
- C # (usando Reflection)
- Clojure
- CobolScript
- Lenguaje de marcado ColdFusion
- Common Lisp y la mayoría de los demás Lisps
- Dylan
- mi
- Elixir
- Erlang
- ADELANTE
- Gambas
- GDScript
- Maravilloso [3]
- Java (usando Reflection)
- JavaScript
- Julia
- Lua
- MATLAB / Octava
- C objetivo
- Perl
- PHP
- Potencia Shell
- Prólogo
- Pitón
- R
- Raku
- Rebol
- Rubí
- Charla
- Súper colisionador
- Tcl
- VBScript
- Wolfram Language
Ver también
- Comparación de lenguajes de programación
- Vinculación de nombre
- Arquitectura de von Neumann
Referencias
- ^ Meijer, Erik y Peter Drayton (2005), Escritura estática donde sea posible, Escritura dinámica cuando sea necesario: el fin de la guerra fría entre lenguajes de programación , Microsoft Corporation, CiteSeerX 10.1.1.69.5966
- ^ Capítulo 24. Soporte de lenguaje dinámico . Static.springsource.org. Consultado el 17 de julio de 2013.
- ^ < "Copia archivada" . Archivado desde el original el 2 de marzo de 2014 . Consultado el 2 de marzo de 2014 .CS1 maint: copia archivada como título ( enlace )
Otras lecturas
- Tratt, Laurence (2009). Idiomas escritos dinámicamente . Avances en informática. 77 . págs. 149-184. doi : 10.1016 / s0065-2458 (09) 01205-4 . ISBN 9780123748126.
enlaces externos
(Muchos usan el término "lenguajes de secuencias de comandos").
- Prechelt, Lutz (18 de agosto de 2002). "¿Son buenos los lenguajes de secuencias de comandos? Una validación de Perl, Python, Rexx y Tcl contra C, C ++ y Java" (PDF) . Avances en informática . 57 : 205–270. doi : 10.1016 / S0065-2458 (03) 57005-X . ISSN 0065-2458 . Consultado el 27 de julio de 2020 .
- Bezroukov, Nikolai (2013). "Una visión un poco escéptica sobre los lenguajes de secuencias de comandos" . Softpanorama (2.1 ed.) . Consultado el 27 de julio de 2020 .
- Wall, Larry (6 de diciembre de 2007). Programar es difícil, vamos a programar ... (Discurso). Estado de la cebolla 11. Perl.com . Consultado el 27 de julio de 2020 .
- Roth, Gregor (20 de noviembre de 2007). "Scripting en la plataforma Java" . JavaWorld . Consultado el 27 de julio de 2020 .
- Ousterhout, John K. (marzo de 1998). "Scripting: programación de alto nivel para el siglo XXI" (PDF) . Computadora . Vol. 31 no. 3. págs. 23-30. doi : 10.1109 / 2.660187 . ISSN 0018-9162 . Consultado el 27 de julio de 2020 .
- "ActiveState anuncia enfoque en lenguajes dinámicos" . ActiveState . 26 de julio de 2004 . Consultado el 27 de julio de 2020 .
- Ascher, David (27 de julio de 2004). "Lenguajes dinámicos: listos para los próximos desafíos, por diseño" (PDF) . Libros blancos. ActiveState . Archivado desde el original (PDF) el 18 de noviembre de 2008.
- Ascher, David (27 de julio de 2004). "Lenguajes dinámicos: listos para los próximos desafíos, por diseño" . Libros blancos. ActiveState . Archivado desde el original el 8 de diciembre de 2008.