Un lenguaje de programación dinámico es un tipo de lenguaje que permite determinar y ejecutar diversas operaciones en tiempo de ejecución. Esto difiere de la fase de compilación. Las decisiones clave sobre variables, llamadas a métodos o tipos de datos se toman durante la ejecución del programa, a diferencia de los lenguajes estáticos , donde la estructura y los tipos se fijan durante la compilación. Los lenguajes dinámicos ofrecen flexibilidad, lo que permite a los desarrolladores escribir código más adaptable y conciso.
Por ejemplo, en un lenguaje dinámico, una variable puede comenzar siendo un entero. Posteriormente, se le puede asignar un tipo de dato de cadena sin necesidad de declaraciones de tipo explícitas. Esta característica del tipado dinámico permite una programación más fluida y menos restrictiva. Los desarrolladores pueden centrarse en la lógica y la funcionalidad en lugar de en las limitaciones del lenguaje.
Implementación
Evaluación
Algunos lenguajes dinámicos ofrecen una función `eval` . Esta función toma una cadena o un árbol de sintaxis abstracta que contiene código del lenguaje y lo ejecuta. Si este código representa una expresión, se devuelve el valor resultante. Erik Meijer y Peter Drayton distinguen la generación de código en tiempo de ejecución que ofrece `eval` de la carga dinámica que ofrecen las bibliotecas compartidas y advierten que, en muchos casos, `eval` se utiliza simplemente para implementar funciones de orden superior (pasando funciones como cadenas) o para la deserialización . [ 1 ]
Modificación en tiempo de ejecución del objeto
En un lenguaje dinámico, un sistema de tipos u objetos generalmente se puede modificar durante la ejecución. Esto puede implicar la generación de nuevos objetos a partir de una definición en tiempo de ejecución o mediante la combinación de tipos u objetos existentes. También puede referirse a la modificación de la herencia o el árbol de tipos, alterando así el comportamiento de los tipos existentes (especialmente en lo que respecta a la invocación de métodos ).
Inferencia de tipo
Dado que muchos lenguajes dinámicos incluyen un sistema de tipos dinámico, la inferencia de tipos en tiempo de ejecución basada en valores para la interpretación interna es una tarea común. Como los tipos de valor pueden cambiar durante la interpretación, se utiliza con frecuencia al realizar operaciones atómicas.
Asignación de memoria variable
Los lenguajes de programación estáticos (posiblemente de forma indirecta) requieren que los desarrolladores definan el tamaño de la memoria utilizada antes de la compilación (a menos que se recurra a la lógica de punteros). En consonancia con la modificación en tiempo de ejecución de objetos, los lenguajes dinámicos necesitan implícitamente reasignar memoria en función de las operaciones individuales del programa.
Reflexión
La programación reflexiva (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 y modificación completas del código de un programa como datos, como en las funcionalidades que Lisp ofrece para analizar expresiones S.
Macros
Un número limitado de lenguajes de programación dinámicos ofrece 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 la evaluación en una característica llamada macros . La mayoría de los programadores que conocen el término macro las han encontrado en C o C++ , donde son una característica estática integrada en un pequeño subconjunto del lenguaje, y solo permiten sustituciones de cadenas en el texto del programa. En los lenguajes dinámicos, sin embargo, proporcionan acceso al funcionamiento interno del compilador y acceso completo al intérprete, la máquina virtual o el entorno de ejecución, lo que permite definir construcciones similares a las del lenguaje que pueden optimizar el código o modificar la sintaxis o la gramática del lenguaje.
En general, el lenguaje ensamblador , C , C++ , las primeras versiones de Java y Fortran no encajan en esta categoría.
Se considera que el primer lenguaje de programación dinámico fue Lisp (McCarthy, 1965), que continuó influyendo en el diseño de lenguajes de programación hasta nuestros días. [ 2 ]
Código de ejemplo
Los siguientes ejemplos muestran características dinámicas que utilizan el lenguaje Common Lisp y su sistema de objetos Common Lisp (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 de 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 bajo el nombre best-guess CL-USER > ( compile 'best-guess *best-guess-formula* ) # <Function 15 40600152F4>; la función puede ser llamada 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* ) # <Function 16 406000085C>; la siguiente llamada invocará la nueva función, una característica del enlace tardío CL-USER > ( mejor estimación 10.3 ) 16.28573Modificación en tiempo de ejecución del objeto
Este ejemplo muestra cómo se puede modificar una instancia existente para incluir una nueva ranura cuando cambia su clase, y cómo se puede reemplazar un método existente por una nueva versión.
; una clase persona. La persona tiene un nombre. CL-USER > ( defclass person () (( name :initarg :name ))) # <STANDARD-CLASS PERSON 4020081FB3>; un método de impresión personalizado para los objetos de la clase person CL-USER > ( defmethod print-object (( p person ) stream ) ( print-unreadable-object ( p stream :type t ) ( format stream "~a" ( slot-value p 'name )))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON T ) 4020066E5B>; un ejemplo de instancia de persona CL-USER > ( setf *person-1* ( make-instance 'person :name "Eva Luator" )) # <PERSONA Eva Luator>; la clase persona obtiene una segunda ranura. Luego tiene las ranuras nombre y edad. CL-USER > ( defclass person () (( name :initarg :name ) ( age :initarg :age :initform :unknown ))) # <STANDARD-CLASS PERSON 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 'name ) ( slot-value p 'age )))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON T ) 402022ADE3>; el objeto existente ahora ha cambiado, tiene una ranura adicional y un nuevo método de impresión CL-USER > *person-1* # <PERSONA Eva Luator edad: DESCONOCIDA>; podemos establecer el nuevo intervalo de edad de la instancia CL-USER > ( setf ( slot-value *person-1* 'age ) 25 ) 25; el objeto ha sido actualizado CL-USER > *persona-1* # <PERSONA Eva Luator edad: 25>Ensamblaje de código en tiempo de ejecución basado en la clase de instancias.
En el siguiente ejemplo, la clase `person` obtiene una nueva superclase. El método `print` se redefine de manera que combina varios métodos en un método efectivo. Este método efectivo se construye en función de la clase del argumento y de los métodos disponibles y aplicables en tiempo de ejecución.
; la clase persona CL-USER > ( defclass person () (( name :initarg :name ))) # <STANDARD-CLASS PERSON 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 )))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON 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* # <PERSONA Eva Luator>; ahora se redefine el método print para que sea extensible ; el método around crea el contexto para el método print y llama al siguiente método CL-USER > ( defmethod print-object :around (( p person ) stream ) ( print-unreadable-object ( p stream :type t ) ( call-next-method ))) # <STANDARD-METHOD PRINT-OBJECT ( :AROUND ) ( PERSON T ) 4020263743>; el método principal imprime el nombre CL-USER > ( defmethod print-object (( p person ) stream ) ( format stream "~a" ( slot-value p 'name ))) # <STANDARD-METHOD PRINT-OBJECT NIL ( PERSON T ) 40202646BB>; una nueva clase id-mixin proporciona un id CL-USER > ( defclass id-mixin () (( id :initarg :id ))) # <STANDARD-CLASS ID-MIXIN 422034A7AB>; el método print simplemente imprime el valor de la ranura id CL-USER > ( defmethod print-object :after (( object id-mixin ) stream ) ( format stream " ID: ~a" ( slot-value object 'id ))) # <STANDARD-METHOD PRINT-OBJECT ( :AFTER ) ( ID-MIXIN T ) 4020278E33>; ahora redefinimos la clase person para incluir el mixin id-mixin CL-USER > ( defclass person ( id-mixin ) (( name :initarg :name ))) # <STANDARD-CLASS PERSON 4220333E23>; la instancia existente *persona-1* ahora tiene una nueva ranura y la establecemos en 42 CL-USER > ( setf ( slot-value *persona-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 primary y el método after. CL-USER > *person-1* # <PERSONA Eva Luator ID: 42>Ejemplos
Entre los lenguajes de programación dinámicos más populares se encuentran JavaScript , Python , Ruby , PHP , Lua y Perl . Los siguientes se consideran generalmente lenguajes dinámicos:
- ActionScript
- BeanShell [ 3 ]
- C# (usando reflexión)
- Clojure
- CobolScript
- Lenguaje de marcado ColdFusion
- Lisp común y la mayoría de los demás Lisp
- Dylan
- mi
- Elixir
- Erlang
- Adelante
- Gambas
- GDScript
- Genial [ 4 ]
- Java (usando reflexión)
- JavaScript
- Julia
- Lua
- MATLAB – Octave
- Objetivo-C
- REXX de objetos (ooRexx)
- Perl
- PHP
- PowerShell
- Prólogo
- Pitón
- R
- Raku
- Rebol
- Rubí
- Charla informal
- Supercolisionador
- Tcl
- VBScript
- Lenguaje Wolfram
Véase también
Referencias
- ↑ Meijer, Erik y Peter Drayton (2005), Tipado estático donde sea posible, tipado dinámico cuando sea necesario: El fin de la guerra fría entre lenguajes de programación (PDF) , Microsoft Corporation, CiteSeerX 10.1.1.69.5966
- ↑ Harper, Robert (2016). Fundamentos prácticos de los lenguajes de programación . Nueva York: Cambridge University Press. pág. 195. ISBN 9-781107-150300.
- ↑ Capítulo 24. Soporte dinámico de lenguajes . Static.springsource.org. Consultado el 17 de julio de 2013.
- ↑ "Groovy - Inicio" . Archivado del original el 2 de marzo de 2014. Consultado el 2 de marzo de 2014 .
Lecturas adicionales
Enlaces externos
(Muchos utilizan el término "lenguajes de scripting").
- Prechelt, Lutz (18 de agosto de 2002). "¿Son buenos los lenguajes de scripting? Una validación de Perl, Python, Rexx y Tcl frente a C, C++ y Java" (PDF) . Advances in Computers . 57 : 205–270 . doi : 10.1016/S0065-2458(03)57005-X . ISBN 9780120121571ISSN 0065-2458 . Consultado el 27 de julio de 2020 .
- Bezroukov, Nikolai (2013). "Una visión ligeramente escéptica sobre los lenguajes de scripting" . Softpanorama ( ed. 2.1) . Recuperado el 27 de julio de 2020 .
- Wall, Larry (6 de diciembre de 2007). Programar es difícil, ¡vamos a programar scripts! (Discurso). State of the Onion 11. Perl.com . Consultado el 27 de julio de 2020 .
- Roth, Gregor (20 de noviembre de 2007). "Scripting en la plataforma Java" . JavaWorld . Recuperado el 27 de julio de 2020 .
- Ousterhout, John K. (March 1998). "Scripting: Higher-Level Programming for the 21st Century"(PDF). Computer. Vol. 31, no. 3. pp. 23–30. doi:10.1109/2.660187. ISSN 0018-9162. Archived from the original(PDF) on 2020-07-27. Retrieved 2020-07-27.
- "ActiveState Announces Focus on Dynamic Languages". ActiveState. July 26, 2004. Retrieved 2020-07-27.
- Ascher, David (July 27, 2004). "Dynamic Languages — ready for the next challenges, by design"(PDF). Whitepapers. ActiveState. Archived from the original(PDF) on 2008-11-18.
- Ascher, David (July 27, 2004). "Dynamic Languages – ready for the next challenges, by design". Whitepapers. ActiveState. Archived from the original on 2008-12-08.
- Estrategia de evaluación
- Lenguajes de programación dinámicos