D (lenguaje de programación)

Lenguaje de programación de sistemas multiparadigma

Lenguaje de programación D
ParadigmaMultiparadigma : funcional , imperativo , orientado a objetos
Diseñado porWalter Bright , Andrei Alexandrescu (desde 2007)
ReveladorFundación del lenguaje D
Apareció por primera vez8 de diciembre de 2001 ; hace 22 años [1] ( 08-12-2001 )
Versión estable
2.109.1 [2]  / 1 de julio de 2024 ; hace 3 meses ( 1 de julio de 2024 )
Disciplina de mecanografíaInferido , estático , fuerte
Sistema operativoFreeBSD , Linux , macOS , Windows
LicenciaImpulsar [3] [4] [5]
Extensiones de nombre de archivo.d [6] [7]
Sitio webes:dlang.org
Implementaciones principales
DMD ( implementación de referencia ), GCC,

GDC,

Países menos adelantados (PMA), Países menos adelantados (SDC)
Influenciado por
BÁSICO , [8] C , C++ , C# , Eiffel , [9] Java , Python
Influenciado
Genie, MiniD, Qore , Swift , [10] Vala , C++11 , C++14 , C++17 , C++20 , Go , C# , otros
  • Programación en D en Wikilibros

D , también conocido como dlang , es un lenguaje de programación de sistemas multiparadigma creado por Walter Bright en Digital Mars y lanzado en 2001. Andrei Alexandrescu se unió al esfuerzo de diseño y desarrollo en 2007. Aunque se originó como una reingeniería de C++ , D es ahora un lenguaje muy diferente. A medida que se ha desarrollado, se ha inspirado en otros lenguajes de programación de alto nivel . En particular, ha sido influenciado por Java , Python , Ruby , C# y Eiffel .

La referencia del lenguaje D lo describe de la siguiente manera:

D es un lenguaje de programación de sistemas de propósito general con una sintaxis similar a C que se compila en código nativo. Tiene tipado estático y admite la gestión de memoria tanto automática (recolección de basura) como manual. Los programas D están estructurados como módulos que se pueden compilar por separado y vincular con bibliotecas externas para crear bibliotecas nativas o ejecutables. [11]

Características

En general, D no es compatible con el código fuente de C y C++. Sin embargo, cualquier código que sea legal tanto en C como en D debería comportarse de la misma manera.

Al igual que C++, D tiene cierres , funciones anónimas , ejecución de funciones en tiempo de compilación , rangos, conceptos de iteración de contenedores integrados e inferencia de tipos . Las sintaxis de declaración, instrucción y expresión de D también coinciden estrechamente con las de C++.

A diferencia de C++, D también implementa diseño por contrato , módulos , recolección de basura , matrices de primera clase , segmentación de matrices , funciones anidadas y evaluación diferida . D utiliza herencia simple al estilo Java con interfaces y mixins en lugar de herencia múltiple al estilo C++ .

D es un lenguaje de programación de sistemas. Al igual que C++, y a diferencia de los lenguajes de aplicación como Java y C# , D admite la programación de bajo nivel , incluido el ensamblador en línea . El ensamblador en línea permite a los programadores ingresar código ensamblador específico de la máquina dentro del código D estándar. Los programadores de sistemas utilizan este método para acceder a las características de bajo nivel del procesador que se necesitan para ejecutar programas que interactúan directamente con el hardware subyacente , como sistemas operativos y controladores de dispositivos . La programación de bajo nivel también se utiliza para escribir código de mayor rendimiento que el que produciría un compilador .

D admite la sobrecarga de funciones y la sobrecarga de operadores . Los símbolos ( funciones , variables , clases ) se pueden declarar en cualquier orden; no se necesitan declaraciones anticipadas .

En D, las cadenas de caracteres de texto son matrices de caracteres, y las matrices en D tienen límites controlados. [12] D tiene tipos de primera clase para números complejos e imaginarios. [13]

Paradigmas de programación

D admite cinco paradigmas de programación principales :

Imperativo

La programación imperativa en D es casi idéntica a la de C. Las funciones, datos, instrucciones, declaraciones y expresiones funcionan igual que en C, y se puede acceder directamente a la biblioteca de ejecución de C. Por otro lado, a diferencia de C, la foreachconstrucción de bucle de D permite realizar bucles sobre una colección. D también permite funciones anidadas , que son funciones que se declaran dentro de otra función y que pueden acceder a las variables locales de la función que las contiene .

importar std . stdio ; void main () { int multiplicador = 10 ; int escalado ( int x ) { return x * multiplicador ; }                foreach ( i ; 0 .. 10 ) { writefln ( "Hola, mundo %d! scaled = %d" , i , scaled ( i )); } }         

Orientado a objetos

La programación orientada a objetos en D se basa en una única jerarquía de herencia , en la que todas las clases se derivan de la clase Object. D no admite la herencia múltiple; en su lugar, utiliza interfaces de estilo Java , que son comparables a las clases abstractas puras de C++, y mixins , que separan la funcionalidad común de la jerarquía de herencia. D también permite la definición de métodos estáticos y finales (no virtuales) en interfaces.

Las interfaces y la herencia en D admiten tipos covariantes para los tipos de retorno de métodos anulados.

D admite el reenvío de tipos, así como el envío dinámico personalizado opcional .

Las clases (e interfaces) en D pueden contener invariantes que se verifican automáticamente antes y después de la entrada a métodos públicos, de acuerdo con la metodología de diseño por contrato .

Muchos aspectos de las clases (y estructuras) se pueden introspeccionar automáticamente en tiempo de compilación (una forma de programación reflexiva (reflexión) usando type traits) y en tiempo de ejecución (RTTI / TypeInfo), para facilitar la generación de código genérico o automática de código (generalmente usando técnicas de tiempo de compilación).

Funcional

D admite características de programación funcional como literales de función , cierres , objetos recursivamente inmutables y el uso de funciones de orden superior . Existen dos sintaxis para funciones anónimas, que incluyen una forma de múltiples declaraciones y una notación de expresión única "abreviada": [14]

int function ( int ) g ; g = ( x ) { return x * x ; }; // expresión larga g = ( x ) => x * x ; // expresión abreviada                  

Hay dos tipos integrados para los literales de función, function, que es simplemente un puntero a una función asignada a la pila, y delegate, que también incluye un puntero al marco de pila relevante , el "entorno" circundante, que contiene las variables locales actuales. La inferencia de tipos se puede utilizar con una función anónima, en cuyo caso el compilador crea un delegatea menos que pueda probar que un puntero de entorno no es necesario. Del mismo modo, para implementar un cierre, el compilador coloca las variables locales incluidas en el montón solo si es necesario (por ejemplo, si otra función devuelve un cierre y sale del ámbito de esa función). Al utilizar la inferencia de tipos, el compilador también agregará atributos como purey nothrowal tipo de una función, si puede probar que se aplican.

Otras características funcionales, como currificación y funciones comunes de orden superior como map , filter y reduce, están disponibles a través de los módulos de la biblioteca estándar std.functionaly std.algorithm.

importar std.stdio , std.algoritmo , std.rango ;   vacío principal () { int [] a1 = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]; int [] a2 = [ 6 , 7 , 8 , 9 ];                       // debe ser inmutable para permitir el acceso desde dentro de una función pura inmutable pivot = 5 ;     int mySum ( int a , int b ) pure nothrow /* función pura */ { if ( b <= pivot ) // referencia al ámbito envolvente return a + b ; de lo contrario return a ; }                      // pasar un delegado (cierre) auto result = reduce ! mySum ( chain ( a1 , a2 )); writeln ( "Resultado: " , result ); // Resultado: 15         // pasar un literal delegado result = reduce !(( a , b ) => ( b <= pivot ) ? a + b : a )( chain ( a1 , a2 )); writeln ( "Resultado: " , resultado ); // Resultado: 15 }                  

Como alternativa, las composiciones de funciones anteriores se pueden expresar utilizando la sintaxis de llamada de función uniforme (UFCS) para una lectura de izquierda a derecha más natural:

 auto resultado = a1 . chain ( a2 ). reduce ! mySum (); writeln ( "Resultado: " , resultado );      resultado = a1 . cadena ( a2 ). reduce !(( a , b ) => ( b <= pivote ) ? a + b : a )(); writeln ( "Resultado: " , resultado );               

Paralelismo

Los conceptos de programación paralela se implementan en la biblioteca y no requieren soporte adicional del compilador. Sin embargo, el sistema de tipos D y el compilador garantizan que el uso compartido de datos se pueda detectar y gestionar de forma transparente.

importar std . stdio : writeln ; importar std . range : iota ; importar std . parallelism : paralelo ;         void main () { foreach ( i ; iota ( 11 ). parallel ) { // El cuerpo del bucle foreach se ejecuta en paralelo para cada i writeln ( "processing " , i ); } }          

iota(11).paralleles equivalente a std.parallelism.parallel(iota(11))utilizar UFCS.

El mismo módulo también admite taskPooloperaciones que pueden utilizarse para la creación dinámica de tareas paralelas, así como operaciones de estilo map-filter-reduce y fold en rangos (y matrices), lo que resulta útil cuando se combina con operaciones funcionales. std.algorithm.mapdevuelve un rango evaluado de forma diferida en lugar de una matriz. De esta manera, cada tarea de trabajo calcula los elementos en paralelo de forma automática.

importar std . stdio : writeln ; importar std . algoritmo : mapa ; importar std . rango : iota ; importar std . paralelismo : taskPool ;            /* En Intel i7-3930X y gdc 9.3.0: * 5140 ms usando std.algorithm.reduce * 888 ms usando std.parallelism.taskPool.reduce * * En AMD Threadripper 2950X y gdc 9.3.0: * 2864 ms usando std.algorithm.reduce * 95 ms usando std.parallelism.taskPool.reduce */ void main () { auto nums = iota ( 1.0 , 1_000_000_000.0 );        auto x = taskPool . reduce ! "a + b" ( 0.0 , map ! "1.0 / (a ​​* a)" ( nums ) );       writeln ( "Suma: " , x ); } 

Concurrencia

La concurrencia está completamente implementada en la biblioteca y no requiere soporte del compilador. Son posibles implementaciones y metodologías alternativas para escribir código concurrente. El uso del sistema de tipado D ayuda a garantizar la seguridad de la memoria.

importar std . stdio , std . concurrency , std . variant ;   vacío foo () { bool cont = verdadero ;       mientras ( cont ) { recibir ( // Los delegados se utilizan para hacer coincidir el tipo de mensaje. ( int msg ) => writeln ( "int received: " , msg ), ( Tid sender ) { cont = false ; sender . send (- 1 ); }, ( Variante v ) => writeln ( "huh?" ) // La variante coincide con cualquier tipo ); } }                        void main () { auto tid = spawn (& foo ); // genera un nuevo hilo que ejecuta foo()        foreach ( i ; 0 .. 10 ) tid.send ( i ); // envía algunos números enteros       tid . send ( 1.0f ); // envía un float tid . send ( "hello" ); // envía una cadena tid . send ( thisTid ); // envía una estructura (Tid)      recibir (( int x ) => writeln ( "El hilo principal recibió el mensaje: " , x )); }    

Metaprogramación

La metaprogramación se apoya en plantillas, ejecución de funciones en tiempo de compilación, tuplas y combinaciones de cadenas. Los siguientes ejemplos demuestran algunas de las características de tiempo de compilación de D.

Las plantillas en D se pueden escribir en un estilo más imperativo en comparación con el estilo funcional de C++ para plantillas. Esta es una función regular que calcula el factorial de un número:

factorial ulong ( ulong n ) { si ( n < 2 ) devuelve 1 ; de lo contrario, devuelve n * factorial ( n - 1 ); }              

Aquí, static ifse demuestra el uso de la construcción condicional de tiempo de compilación de D, para construir una plantilla que realiza el mismo cálculo utilizando un código similar al de la función anterior:

plantilla Factorial ( ulong n ) { estático si ( n < 2 ) enumeración Factorial = 1 ; de lo contrario enumeración Factorial = n * Factorial !( n - 1 ); }                   

En los dos ejemplos siguientes, se utilizan la plantilla y la función definidas anteriormente para calcular factoriales. No es necesario especificar explícitamente los tipos de constantes, ya que el compilador infiere sus tipos a partir de los lados derechos de las asignaciones:

enumeración fact_7 = Factorial !( 7 );   

Este es un ejemplo de ejecución de función en tiempo de compilación (CTFE). Las funciones comunes se pueden utilizar en expresiones constantes en tiempo de compilación siempre que cumplan con ciertos criterios:

enumeración fact_9 = factorial ( 9 );   

La std.string.formatfunción realiza printfun formateo de datos similar (también en tiempo de compilación, a través de CTFE), y el pragma "msg" muestra el resultado en tiempo de compilación:

importar std . string : formato ; pragma ( msg , formato ( "7! = %s" , hecho_7 )); pragma ( msg , formato ( "9! = %s" , hecho_9 ));       

Los mixins de cadenas, combinados con la ejecución de funciones en tiempo de compilación, permiten la generación de código D mediante operaciones de cadenas en tiempo de compilación. Esto se puede utilizar para analizar lenguajes específicos del dominio , que se compilarán como parte del programa:

import FooToD ; // módulo hipotético que contiene una función que analiza el código fuente de Foo // y devuelve el código D equivalente void main () { mixin ( fooToD ( import ( "example.foo" ))); }      

Gestión de la memoria

La memoria se suele gestionar con recolección de basura , pero es posible que objetos específicos se finalicen inmediatamente cuando quedan fuera del alcance. Esto es lo que utilizan la mayoría de los programas y bibliotecas escritos en D.

En caso de que se necesite más control sobre el diseño de la memoria y un mejor rendimiento, es posible una gestión explícita de la memoria utilizando el operador sobrecargado new , llamando directamente a malloc y free de C , o implementando esquemas de asignador personalizados (es decir, en pila con respaldo, asignación de estilo RAII, conteo de referencias, conteo de referencias compartidas). La recolección de basura se puede controlar: los programadores pueden agregar y excluir rangos de memoria para que no sean observados por el recolector, pueden deshabilitar y habilitar el recolector y forzar un ciclo de recolección generacional o completo. [15] El manual proporciona muchos ejemplos de cómo implementar diferentes esquemas de gestión de memoria altamente optimizados para cuando la recolección de basura es inadecuada en un programa. [16]

En las funciones, structlas instancias se asignan de forma predeterminada en la pila, mientras que classlas instancias se asignan de forma predeterminada en el montón (con solo referencia a la instancia de clase que está en la pila). Sin embargo, esto se puede cambiar para las clases, por ejemplo, utilizando la plantilla de la biblioteca estándar std.typecons.scopedo utilizando newestructuras for y asignando a un puntero en lugar de una variable basada en valores. [17]

En las funciones, se asignan matrices estáticas (de tamaño conocido) en la pila. Para matrices dinámicas, se puede utilizar la core.stdc.stdlib.allocafunción (similar a allocaC) para asignar memoria en la pila. El puntero devuelto se puede utilizar (reconvertir) en una matriz dinámica (tipificada) mediante una porción (sin embargo, se debe evitar cambiar el tamaño de la matriz, incluida la adición de datos; y por razones obvias, no se deben devolver desde la función). [17]

Una scopepalabra clave se puede utilizar para anotar partes del código, pero también variables y clases/estructuras, para indicar que deben destruirse (se debe llamar al destructor) inmediatamente al salir del ámbito. La memoria que se desasigne también depende de la implementación y de las diferencias entre clases y estructuras. [18]

std.experimental.allocatorContiene plantillas de asignadores modulares y componibles para crear asignadores personalizados de alto rendimiento para casos de uso especiales. [19]

Seguro D

SafeD [20] es el nombre que se le da al subconjunto de D que se puede garantizar que es seguro para la memoria . Las funciones marcadas @safese verifican en tiempo de compilación para garantizar que no utilicen ninguna característica, como aritmética de punteros y conversiones no verificadas, que podrían provocar la corrupción de la memoria. Cualquier otra función llamada también debe marcarse como @safeo @trusted. Las funciones se pueden marcar @trustedpara los casos en los que el compilador no puede distinguir entre el uso seguro de una característica que está deshabilitada en SafeD y un posible caso de corrupción de la memoria. [21]

Alcance de seguridad de por vida

Inicialmente bajo los nombres de DIP1000 [22] y DIP25 [23] (ahora parte de la especificación del lenguaje [24] ), D proporciona protección contra ciertas construcciones mal formadas que involucran la duración de los datos.

Los mecanismos actuales en funcionamiento tratan principalmente con parámetros de función y memoria de pila; sin embargo, es una ambición declarada de los líderes del lenguaje de programación proporcionar un tratamiento más exhaustivo de los tiempos de vida dentro del lenguaje de programación D [25] (influenciado por las ideas del lenguaje de programación Rust ).

Seguridad de las asignaciones durante toda la vida

Dentro del código @safe, se verifica la duración de una asignación que involucra un tipo de referencia para garantizar que la duración del cesionario sea más larga que la del asignado.

Por ejemplo:

@safe void test () { int tmp = 0 ; // #1 int * rad ; // #2 rad = & tmp ; // Si se invierte el orden de las declaraciones de #1 y #2, esto falla. { int bad = 45 ; // La duración de vida de "bad" solo se extiende al ámbito en el que está definido. * rad = bad ; // Esto es válido. rad = & bad ; // La duración de vida de rad es más larga que bad, por lo tanto, esto no es válido. } }                              

Anotaciones de duración de los parámetros de función dentro del código @safe

Cuando se aplica a parámetros de función que son de tipo puntero o referencias, las palabras clave return y scope restringen la duración y el uso de ese parámetro.

El estándar del lenguaje dicta el siguiente comportamiento: [26]

Clase de almacenamientoComportamiento (y restricciones) de un parámetro con la clase de almacenamiento
alcanceLas referencias en el parámetro no se pueden escapar. Se ignoran en el caso de parámetros sin referencias.
devolverEl parámetro puede devolverse o copiarse en el primer parámetro, pero de lo contrario no se escapa de la función. Se requiere que dichas copias no sobrevivan al argumento o argumentos de los que se derivaron. Se ignoran para parámetros sin referencias

A continuación se ofrece un ejemplo anotado.

@seguro :int * gp ; void thorin ( ámbito int *); void gloin ( int *); int * balin ( return ámbito int * p , ámbito int * q , int * r ) { gp = p ; // Error, p escapa a la variable global gp. gp = q ; // Error, q escapa a la variable global gp. gp = r ; // OK.                           thorin ( p ); // OK, p no escapa a thorin(). thorin ( q ); // OK. thorin ( r ); // OK.      gloino ( p ); // Error, p escapa de gloin(). gloino ( q ); // Error, q escapa de gloin(). gloino ( r ); // Está bien que r escape de gloin().      devolver p ; // OK. devolver q ; // Error, no se puede devolver 'scope' q. devolver r ; // OK. }        

Interacción con otros sistemas

Se admite la interfaz binaria de aplicación (ABI) de C , así como todos los tipos fundamentales y derivados de C, lo que permite el acceso directo al código y las bibliotecas de C existentes. Los enlaces de D están disponibles para muchas bibliotecas de C populares. Además, la biblioteca estándar de C es parte del D estándar.

En Microsoft Windows, D puede acceder al código del Modelo de objetos componentes (COM).

Siempre que se tenga en cuenta la gestión de memoria de forma adecuada, se pueden mezclar muchos otros lenguajes con D en un único binario. Por ejemplo, el compilador GDC permite vincular y entremezclar códigos de C, C++ y otros lenguajes compatibles, como Objective-C. El código D (funciones) también se puede marcar como que utiliza ABIs de C, C++ y Pascal y, por lo tanto, se puede pasar a las bibliotecas escritas en estos lenguajes como callbacks . De manera similar, se pueden intercambiar datos entre los códigos escritos en estos lenguajes de ambas formas. Esto suele restringir el uso a tipos primitivos, punteros, algunas formas de matrices, uniones , estructuras y solo algunos tipos de punteros de función.

Dado que muchos otros lenguajes de programación suelen proporcionar la API de C para escribir extensiones o ejecutar el intérprete de los lenguajes, D también puede interactuar directamente con estos lenguajes, utilizando enlaces estándar de C (con un archivo de interfaz de D delgado). Por ejemplo, existen enlaces bidireccionales para lenguajes como Python , [27] Lua [28] [29] y otros lenguajes, que a menudo utilizan métodos de generación de código en tiempo de compilación y reflexión de tipos en tiempo de compilación.

Interacción con código C++

Para el código D marcado como extern(C++), se especifican las siguientes características:

  • Las convenciones de manipulación de nombres deberán coincidir con las de C++ en el destino.
  • Para las llamadas de función, la ABI deberá ser equivalente.
  • La vtable deberá coincidir con la herencia única (el único nivel admitido por la especificación del lenguaje D).

Los espacios de nombres de C++ se utilizan a través de la sintaxis extern(C++, namespace)donde espacio de nombres es el nombre del espacio de nombres de C++.

Un ejemplo de interoperación en C++

El lado C++

importar < imprimir > ; clase Base { público : virtual void print3i ( int a , int b , int c ) = 0 ; };             clase Derivada : pública Base { pública : int campo ; Derivada ( int campo ) : campo ( campo ) {}              void print3i ( int a , int b , int c ) { std :: println ( "a = {}" , a ); std :: println ( "b = {}" , b ); std :: println ( "c = {}" , c ); }               int mul ( int factor ); };  int Derivado::mul ( int factor ) { devolver campo * factor ; }       Derivado * createInstance ( int i ) { return new Derivado ( i ); }      void deleteInstance ( Derivado *& d ) { eliminar d ; d = 0 ; }        

El lado D

extern ( C ++) { clase abstracta Base { void print3i ( int a , int b , int c ); }              clase Derivada : Base { int campo ; @disable this (); anular void print3i ( int a , int b , int c ); final int mul ( int factor ); }                      Derivado createInstance ( int i ); void deleteInstance ( ref Derivado d ); }      vacío principal () { importar std . stdio ;     auto d1 = crearInstancia ( 5 ) ; writeln ( d1.campo ) ; writeln ( d1.mul ( 4 ) ) ;      Base b1 = d1 ; b1 . print3i ( 1 , 2 , 3 );       deleteInstance ( d1 ); assert ( d1 es nulo );    auto d2 = createInstance ( 42 ) ; writeln ( d2.campo ) ;     deleteInstance ( d2 ); assert ( d2 es nulo ); }   

Mejor C

El lenguaje de programación D tiene un subconjunto oficial conocido como " Better C ". [30] Este subconjunto prohíbe el acceso a las características de D que requieren el uso de bibliotecas de tiempo de ejecución distintas a las de C.

Habilitado a través de los indicadores del compilador "-betterC" en DMD y LDC, y "-fno-druntime" en GDC, Better C solo puede llamar al código D compilado bajo el mismo indicador (y código vinculado que no sea D), pero el código compilado sin la opción Better C puede llamar al código compilado con ella: esto, sin embargo, conducirá a comportamientos ligeramente diferentes debido a las diferencias en cómo C y D manejan las afirmaciones.

Características incluidas en Better C

  • Uso sin restricciones de las funciones de tiempo de compilación (por ejemplo, las funciones de asignación dinámica de D se pueden usar en tiempo de compilación para preasignar datos de D)
  • Funciones completas de metaprogramación
  • Funciones anidadas, estructuras anidadas, delegados y lambdas
  • Funciones miembro, constructores, destructores, sobrecarga operativa, etc.
  • El sistema de módulo completo
  • Segmentación de matrices y comprobación de límites de matrices
  • RAII
  • alcance(salida)
  • Protecciones de seguridad de la memoria
  • Interfaz con C++
  • Clases COM y clases C++
  • Las fallas de afirmación se dirigen a la biblioteca de tiempo de ejecución de C
  • cambiar con cuerdas
  • interruptor final
  • bloques de prueba unitaria
  • Validación del formato printf

Características excluidas de Better C

  • Recolección de basura
  • TypeInfo y ModuleInfo
  • Subprocesos incorporados (por ejemplo, core.thread)
  • Matrices dinámicas (aunque también funcionan porciones de matrices estáticas) y matrices asociativas
  • Excepciones
  • sincronizado ycore.sync
  • Constructores o destructores de módulos estáticos

Historia

Walter Bright comenzó a trabajar en un nuevo lenguaje en 1999. D se lanzó por primera vez en diciembre de 2001 [1] y alcanzó la versión 1.0 en enero de 2007. [31] La primera versión del lenguaje (D1) se concentró en los paradigmas imperativo, orientado a objetos y metaprogramación, [32] similar a C++.

Algunos miembros de la comunidad D no estaban satisfechos con Phobos, el entorno de ejecución y la biblioteca estándar oficiales de D , y crearon un entorno de ejecución y una biblioteca estándar alternativos llamados Tango. El primer anuncio público de Tango se produjo a los pocos días del lanzamiento de D 1.0. [33] Tango adoptó un estilo de programación diferente, adoptando la programación orientada a objetos y una alta modularidad. Al ser un proyecto dirigido por la comunidad, Tango estaba más abierto a las contribuciones, lo que le permitió progresar más rápido que la biblioteca estándar oficial. En ese momento, Tango y Phobos eran incompatibles debido a las diferentes API de soporte del entorno de ejecución (el recolector de basura, el soporte de subprocesos, etc.). Esto hizo imposible utilizar ambas bibliotecas en el mismo proyecto. La existencia de dos bibliotecas, ambas ampliamente utilizadas, ha dado lugar a una disputa significativa debido a que algunos paquetes utilizan Phobos y otros utilizan Tango. [34]

En junio de 2007, se lanzó la primera versión de D2. [35] El comienzo del desarrollo de D2 marcó la estabilización de D1. La primera versión del lenguaje se colocó en mantenimiento, y solo recibió correcciones y correcciones de errores de implementación. D2 introdujo cambios importantes en el lenguaje, comenzando con su primer sistema const experimental . Más tarde, D2 agregó muchas otras características del lenguaje, como cierres , pureza y soporte para los paradigmas de programación funcional y concurrente. D2 también resolvió problemas de la biblioteca estándar al separar el entorno de ejecución de la biblioteca estándar. La finalización de un puerto de D2 Tango se anunció en febrero de 2012. [36]

El lanzamiento del libro de Andrei Alexandrescu , El lenguaje de programación D , el 12 de junio de 2010, marcó la estabilización de D2, al que hoy en día se le conoce comúnmente simplemente como "D".

En enero de 2011, el desarrollo de D pasó de un sistema de seguimiento de errores y envío de parches a GitHub . Esto ha llevado a un aumento significativo de las contribuciones al compilador, al entorno de ejecución y a la biblioteca estándar. [37]

En diciembre de 2011, Andrei Alexandrescu anunció que D1, la primera versión del lenguaje, se discontinuaría el 31 de diciembre de 2012. [38] La versión final de D1, D v1.076, fue el 31 de diciembre de 2012. [39]

El código para el compilador oficial de D, el compilador Digital Mars D de Walter Bright, fue publicado originalmente bajo una licencia personalizada , que calificaba como fuente disponible pero no se ajustaba a la Definición de Código Abierto . [40] En 2014, el front-end del compilador fue re-licenciado como código abierto bajo la Licencia de Software Boost . [3] Este código re-licenciado excluía el back-end, que había sido desarrollado parcialmente en Symantec . El 7 de abril de 2017, todo el compilador se puso a disposición bajo la licencia Boost después de que Symantec diera permiso para re-licenciar también el back-end. [4] [41] [42] [43] El 21 de junio de 2017, el lenguaje D fue aceptado para su inclusión en GCC. [44]

Implementaciones

La mayoría de las implementaciones actuales de D se compilan directamente en código de máquina .

Compiladores listos para producción:

  • DMD – El compilador Digital Mars D de Walter Bright es el compilador oficial de D; de código abierto bajo la licencia Boost Software License . [3] [4] El frontend DMD es compartido por GDC (ahora en GCC) y LDC, para mejorar la compatibilidad entre compiladores. Inicialmente el frontend estaba escrito en C++, pero ahora la mayor parte está escrita en D (autohospedaje). Los optimizadores de código de máquina y backend se basan en el compilador Symantec. Al principio solo admitía x86 de 32 bits, con soporte agregado para amd64 de 64 bits y PowerPC por Walter Bright. Más tarde, el backend y casi todo el compilador se trasladaron de C++ a D para un autohospedaje completo.
  • GCC – The GNU Compiler Collection , fusionó GDC [45] en GCC 9 el 29 de octubre de 2018. [46] Las primeras versiones funcionales de GDC con GCC, basadas en GCC 3.3 y GCC 3.4 en x86 de 32 bits en Linux y macOS [47] se lanzaron el 22 de marzo de 2004. Desde entonces, GDC ha ganado soporte para plataformas adicionales, mejoró el rendimiento y corrigió errores, al mismo tiempo que rastrea el código DMD ascendente para la interfaz y la especificación del lenguaje. [48]
  • LDC : compilador basado en el front-end DMD que utiliza LLVM como back-end. La primera versión con calidad de lanzamiento se publicó el 9 de enero de 2009. [49] Es compatible con la versión 2.0. [50]

Compiladores de juguetes y de prueba de concepto:

  • Compilador D para .NET : un back-end para el compilador del lenguaje de programación D 2.0. [51] [52] Compila el código en bytecode de lenguaje intermedio común (CIL) en lugar de en código de máquina. El CIL se puede ejecutar a través de una máquina virtual de infraestructura de lenguaje común (CLI) . El proyecto no se ha actualizado en años y el autor indicó que el proyecto ya no está activo.
  • SDC – The Snazzy D Compiler [53] utiliza un front-end personalizado y LLVM como back-end de compilación. Está escrito en D y utiliza un programador para gestionar la resolución de símbolos con el fin de gestionar de forma elegante las características de tiempo de compilación de D. Este compilador actualmente admite un subconjunto limitado del lenguaje. [54] [55]

Usando los compiladores y cadenas de herramientas anteriores, es posible compilar programas D para apuntar a muchas arquitecturas diferentes, incluyendo IA-32 , amd64 , AArch64 , PowerPC , MIPS64 , DEC Alpha , Motorola m68k , SPARC , s390 , WebAssembly . Los principales sistemas operativos soportados son Windows y Linux , pero varios compiladores también soportan Mac OS X , FreeBSD , NetBSD , AIX , Solaris/OpenSolaris y Android , ya sea como host o destino, o ambos. El destino WebAssembly (soportado a través de LDC y LLVM) puede operar en cualquier entorno WebAssembly, como el navegador web moderno ( Google Chrome , Mozilla Firefox , Microsoft Edge , Apple Safari ) o máquinas virtuales Wasm dedicadas.

Herramientas de desarrollo

Los editores y entornos de desarrollo integrados (IDE) que admiten el resaltado de sintaxis y la finalización parcial de código para el lenguaje incluyen SlickEdit , Emacs , vim , SciTE , Smultron , Zeus, [56] y Geany , entre otros. [57]

Existen IDE de código abierto para Windows , algunos escritos en D, como Poseidon, [70] D-IDE, [71] y Entice Designer. [72]

Las aplicaciones D pueden depurarse utilizando cualquier depurador de C/C++, como GNU Debugger (GDB) o WinDbg , aunque el soporte para varias características específicas del lenguaje D es extremadamente limitado. En Windows, los programas D pueden depurarse utilizando Ddbg, o herramientas de depuración de Microsoft (WinDBG y Visual Studio), después de haber convertido la información de depuración utilizando cv2pdb. El depurador ZeroBUGS Archivado el 23 de diciembre de 2017 en Wayback Machine para Linux tiene soporte experimental para el lenguaje D. Ddbg puede utilizarse con varios IDE o desde la línea de comandos; ZeroBUGS tiene su propia interfaz gráfica de usuario (GUI).

DustMite es una herramienta para minimizar el código fuente D, útil para encontrar problemas con el compilador o las pruebas. [73]

dub es un popular administrador de paquetes y compilaciones para aplicaciones y bibliotecas D, y a menudo está integrado en el soporte IDE. [74]

Ejemplos

Ejemplo 1

Este programa de ejemplo imprime sus argumentos de línea de comandos. La mainfunción es el punto de entrada de un programa en D y argses una matriz de cadenas que representan los argumentos de la línea de comandos. A stringen D es una matriz de caracteres, representada por immutable(char)[].

importar std . stdio : writefln ;  void principal ( cadena [] argumentos ) {    foreach ( i , arg ; argumentos )    writefln ( "args[%d] = '%s'" , i , arg );  }

La foreachinstrucción puede iterar sobre cualquier colección. En este caso, produce una secuencia de índices ( i) y valores ( arg) a partir de la matriz args. Los tipos del índice iy del valor argse infieren a partir del tipo de la matriz args.

Ejemplo 2

A continuación se muestran varias capacidades de D y ventajas y desventajas del diseño de D en un programa corto. Itera sobre las líneas de un archivo de texto llamado words.txt, que contiene una palabra diferente en cada línea, e imprime todas las palabras que son anagramas de otras palabras.

importar std.stdio , std.algoritmo , std.rango , std.cadena ;    vacío principal () {   dstring [] [ dstring ] firma2palabras ;   foreach ( dchar [] w ; líneas ( Archivo ( "words.txt" ))) {     w = w .chomp ( ). toLower ();   firma inmutable = w . dup . sort (). release (). idup ;    firma2palabras [ firma ] ~= w . idup ;   } foreach ( palabras ; firma2palabras ) {    si ( palabras . longitud > 1 )    writeln ( palabras . join ( " " )); }}
  1. signature2wordses una matriz asociativa incorporada que asigna claves dstring (32 bits/char) a matrices de dstrings. Es similar a defaultdict(list)en Python .
  2. lines(File())produce líneas de forma diferida, con la nueva línea. Luego se debe copiar con iduppara obtener una cadena que se utilizará para los valores de la matriz asociativa (la iduppropiedad de las matrices devuelve un duplicado inmutable de la matriz, lo cual es necesario ya que el dstringtipo es en realidad immutable(dchar)[]). Las matrices asociativas integradas requieren claves inmutables.
  3. El ~=operador agrega una nueva dstring a los valores de la matriz dinámica asociada.
  4. toLower, joiny chompson funciones de cadena que D permite usar con una sintaxis de método. El nombre de tales funciones suele ser similar a los métodos de cadena de Python. toLowerConvierte una cadena a minúsculas, join(" ")une una matriz de cadenas en una sola cadena usando un solo espacio como separador y chompelimina una nueva línea del final de la cadena si hay una presente. w.dup.sort().release().idupEs más legible, pero equivalente a, release(sort(w.dup)).iduppor ejemplo. Esta característica se llama UFCS (Uniform Function Call Syntax) y permite extender cualquier tipo de paquete integrado o de terceros con una funcionalidad similar a un método. El estilo de escribir código como este a menudo se conoce como pipeline (especialmente cuando los objetos utilizados se calculan de forma diferida, por ejemplo, iteradores/rangos) o interfaz Fluent .
  5. Esta sortes una función de std.algorithm que ordena la matriz en su lugar, creando una firma única para las palabras que son anagramas entre sí. El release()método en el valor de retorno de sort()es útil para mantener el código como una sola expresión.
  6. El segundo foreachitera sobre los valores de la matriz asociativa, es capaz de inferir el tipo de words.
  7. signaturese asigna a una variable inmutable, se infiere su tipo.
  8. dchar[]Se utiliza UTF-32 en lugar del UTF-8 char[] normal, de lo contrario sort()no se ordenará. Hay formas más eficientes de escribir este programa utilizando solo UTF-8.

Usos

Entre las organizaciones notables que utilizan el lenguaje de programación D para proyectos se incluyen Facebook , [75] eBay , [76] y Netflix . [77]

D se ha utilizado con éxito para juegos AAA , [78] intérpretes de lenguaje, máquinas virtuales, [79] [80] un núcleo de sistema operativo , [81] programación de GPU , [82] desarrollo web , [83] [84] análisis numérico , [85] aplicaciones GUI , [86] [87] un sistema de información para pasajeros , [88] aprendizaje automático, [89] procesamiento de texto, servidores web y de aplicaciones e investigación.

El conocido grupo de piratas informáticos norcoreano conocido como Lazarus explotó CVE-2021-44228, también conocido como " Log4Shell ", para implementar tres familias de malware escritas en DLang. [90]

Crítica

La falta de transparencia, agilidad y previsibilidad en el proceso de incorporación de correcciones de fallas y errores conocidos, y la dificultad de introducir cambios menores y mayores en el lenguaje D, se describen de manera inminente en un artículo de blog [91] de un ex colaborador. La aparente frustración descrita allí ha llevado a la bifurcación de OpenD [92] el 1 de enero de 2024.

Véase también

Referencias

  1. ^ ab "Registro de cambios de D hasta el 7 de noviembre de 2005". Lenguaje de programación D 1.0 . Digital Mars . Consultado el 1 de diciembre de 2011 .
  2. ^ "2.109.1" . Consultado el 7 de julio de 2024 .
  3. ^ abc "dmd front end now switched to Boost license" (El front end de DMD ahora se cambió a la licencia Boost) . Consultado el 9 de septiembre de 2014 .
  4. ^ abc "dmd Backend convertido a licencia Boost". 7 de abril de 2017. Consultado el 9 de abril de 2017 .
  5. ^ "Preguntas frecuentes sobre D 2.0" . Consultado el 11 de agosto de 2015 .
  6. ^ "Lenguaje de programación D - Fileinfo.com" . Consultado el 15 de noviembre de 2020 . [ cita requerida ]
  7. ^ "Lenguaje de programación D - dlang.org" . Consultado el 15 de noviembre de 2020 .[ cita requerida ]
  8. ^ "On: Show HN: Una buena API de cadenas C". Hacker News . 3 de diciembre de 2022 . Consultado el 4 de diciembre de 2022 .
  9. ^ Alexandrescu, Andrei (2010). El lenguaje de programación D (Primera edición). Upper Saddle River, Nueva Jersey: Addison-Wesley. pág. 314. ISBN 978-0321635365.
  10. ^ "Construcción de assert() en Swift, Parte 2: __FILE__ y __LINE__" . Consultado el 25 de septiembre de 2014 .
  11. ^ "Introducción al lenguaje de programación D". dlang.org . Consultado el 21 de abril de 2024 .  Este artículo incorpora texto de este trabajo de contenido gratuito . Licenciado bajo BSL-1.0 (declaración de licencia/permiso).
  12. ^ "Cadenas D frente a cadenas C++". Digital Mars. 2012.
  13. ^ "Tipos complejos de D y std::complex de C++". Digital Mars . 2012. Archivado desde el original el 13 de enero de 2008 . Consultado el 4 de noviembre de 2021 .
  14. ^ "Expresiones". Digital Mars . Consultado el 27 de diciembre de 2012 .
  15. ^ "std.gc". Lenguaje de programación D 1.0 . Digital Mars . Consultado el 6 de julio de 2010 .
  16. ^ "Gestión de memoria". Lenguaje de programación D 2.0 . Digital Mars . Consultado el 17 de febrero de 2012 .
  17. ^ ab "Sigue tu propio camino (primera parte: la pila)". El blog de D . 7 de julio de 2017 . Consultado el 7 de mayo de 2020 .
  18. ^ "Atributos - Lenguaje de programación D". dlang.org . Consultado el 7 de mayo de 2020 .
  19. ^ "std.experimental.allocator - Lenguaje de programación D". dlang.org . Consultado el 7 de mayo de 2020 .
  20. ^ Bartosz Milewski. «SafeD – Lenguaje de programación D» . Consultado el 17 de julio de 2014 .
  21. ^ Steven Schveighoffer (28 de septiembre de 2016). «Cómo escribir código @trusted en D» . Consultado el 4 de enero de 2018 .
  22. ^ "Punteros con alcance". GitHub . 3 de abril de 2020.
  23. ^ "Referencias selladas".
  24. ^ "Especificación del lenguaje D: Funciones - Parámetros de alcance de retorno".
  25. ^ "Propiedad y endeudamiento en D". 15 de julio de 2019.
  26. ^ "Especificación del lenguaje D: Funciones - Clases de almacenamiento de parámetros de función".
  27. ^ "PyD". GitHub . 7 de mayo de 2020 . Consultado el 7 de mayo de 2020 .
  28. ^ Parker, Mike. «Paquete derelict-lua en DUB». Registro de paquetes DUB . Consultado el 7 de mayo de 2020 .
  29. ^ Parker, Mike. «Paquete bindbc-lua en DUB». Registro de paquetes DUB . Consultado el 7 de mayo de 2020 .
  30. ^ "Mejor C".
  31. ^ "Registro de cambios de D". Lenguaje de programación D 1.0 . Digital Mars . Consultado el 11 de enero de 2012 .
  32. ^ "Introducción". Lenguaje de programación D 1.0 . Digital Mars . Consultado el 1 de diciembre de 2011 .
  33. ^ "Anunciamos una nueva biblioteca" . Consultado el 15 de febrero de 2012 .
  34. ^ "Wiki4D: Standard Lib" . Consultado el 6 de julio de 2010 .
  35. ^ "Registro de cambios: lenguaje de programación D". Lenguaje de programación D 2.0 . Fundación del lenguaje D. Consultado el 22 de noviembre de 2020 .
  36. ^ "Tango para D2: todos los módulos de usuario portados" . Consultado el 16 de febrero de 2012 .
  37. ^ Walter Bright. "Re: ¿GitHub o dsource?" . Consultado el 15 de febrero de 2012 .
  38. ^ Andrei Alexandrescu. "D1 se discontinuará el 31 de diciembre de 2012" . Consultado el 31 de enero de 2014 .
  39. ^ "Registro de cambios de D". Lenguaje de programación D 1.0 . Digital Mars . Consultado el 31 de enero de 2014 .
  40. ^ "backendlicense.txt". Código fuente de DMD . GitHub. Archivado desde el original el 22 de octubre de 2016 . Consultado el 5 de marzo de 2012 .
  41. ^ "Comentario de Walter Bright en Reddit". 5 de marzo de 2009. Consultado el 9 de septiembre de 2014 .
  42. ^ D-Compiler-unter-freier-Lizenz en linux-magazin.de (2017, en alemán)
  43. ^ cambiar el backend a Boost Licencia n.° 6680 de Walter Bright en github.com
  44. ^ Idioma aceptado para su inclusión en GCC
  45. ^ "GDC".
  46. ^ "Serie de lanzamientos de GCC 9: cambios, nuevas características y correcciones - Proyecto GNU - Free Software Foundation (FSF)". gcc.gnu.org . Consultado el 7 de mayo de 2020 .
  47. ^ "Otra interfaz para GCC". forum.dlang.org . Consultado el 7 de mayo de 2020 .
  48. ^ "Cambios, nuevas características y correcciones en la serie de lanzamiento de GCC 9".
  49. ^ "Proyecto compilador LLVM D en GitHub". GitHub . Consultado el 19 de agosto de 2016 .
  50. ^ "BuildInstructionsPhobosDruntimeTrunk – ldc – Lenguaje de programación D – Trac" . Consultado el 11 de agosto de 2015 .
  51. ^ "Proyecto D .NET en CodePlex". Archivado desde el original el 26 de enero de 2018 . Consultado el 3 de julio de 2010 .
  52. ^ Jonathan Allen (15 de mayo de 2009). "El código fuente del compilador D.NET ya está disponible". InfoQ . Consultado el 6 de julio de 2010 .
  53. ^ "Haga de SDC el compilador de Snazzy D". GitHub . Consultado el 24 de septiembre de 2023 .
  54. ^ DConf 2014: SDC, un compilador D como biblioteca por Amaury Sechet. YouTube . Consultado el 8 de enero de 2014 .Archivado en Ghostarchive y Wayback Machine
  55. ^ "deadalnix/COSUDE". GitHub . Consultado el 8 de enero de 2014 .
  56. ^ "Wiki4D: EditorSupport/ZeusForWindows" . Consultado el 11 de agosto de 2015 .
  57. ^ "Wiki4D: Soporte para editores" . Consultado el 3 de julio de 2010 .
  58. ^ "Basile.B/dexed". GitLab . Consultado el 29 de abril de 2020 .
  59. ^ "Mono-D - D Wiki". wiki.dlang.org . Consultado el 30 de abril de 2020 .
  60. ^ "Mono-D – Compatibilidad con D para MonoDevelop". Archivado desde el original el 1 de febrero de 2012. Consultado el 11 de agosto de 2015 .
  61. ^ "Alojamiento de proyectos de Google" . Consultado el 11 de agosto de 2015 .
  62. ^ "descenso" . Consultado el 11 de agosto de 2015 .
  63. ^ "Visual D - Lenguaje de programación D" . Consultado el 11 de agosto de 2015 .
  64. ^ Schuetze, Rainer (17 de abril de 2020). «rainers/visuald: Visual D - Extensión de Visual Studio para el lenguaje de programación D». github.com . Consultado el 30 de abril de 2020 .
  65. ^ "dlang-vscode". GitHub . Consultado el 21 de diciembre de 2016 .
  66. ^ "code-d". GitHub . Consultado el 21 de diciembre de 2016 .
  67. ^ "Michel Fortin – D para Xcode" . Consultado el 11 de agosto de 2015 .
  68. ^ "Dav1dde/lumen". GitHub . Consultado el 11 de agosto de 2015 .
  69. ^ Michael, Parker (7 de octubre de 2016). «Project Highlight: DlangUI». The D Blog . Consultado el 12 de septiembre de 2024 .{{cite web}}: CS1 maint: estado de la URL ( enlace )
  70. ^ "poseidon" . Consultado el 11 de agosto de 2015 .
  71. ^ "Mono-D – Soporte D para MonoDevelop" . Consultado el 11 de agosto de 2015 .
  72. ^ "Entice Designer – Dprogramming.com – El lenguaje de programación D" . Consultado el 11 de agosto de 2015 .
  73. ^ "¿Qué es DustMite?". GitHub . Consultado el 29 de abril de 2020 .
  74. ^ "dlang/dub: Sistema de gestión de paquetes y compilaciones para D". GitHub . Consultado el 29 de abril de 2020 .
  75. ^ "Under the Hood: warp, un preprocesador rápido de C y C++". 28 de marzo de 2014. Consultado el 4 de enero de 2018 .
  76. ^ "Herramientas de línea de comandos más rápidas en D". 24 de mayo de 2017. Consultado el 4 de enero de 2018 .
  77. ^ "Introducción a Vectorflow". 2 de agosto de 2017. Consultado el 4 de enero de 2018 .
  78. ^ "Quantum Break: juegos AAA con código D" . Consultado el 4 de enero de 2018 .
  79. ^ "Higgs JavaScript Virtual Machine". GitHub . Consultado el 4 de enero de 2018 .
  80. ^ "Implementación AD del lenguaje de programación ECMA 262 (Javascript)". GitHub . Consultado el 4 de enero de 2018 .
  81. ^ "Proyecto destacado: el núcleo PowerNex". 24 de junio de 2016. Consultado el 4 de enero de 2018 .
  82. ^ "DCompute: Ejecutando D en la GPU". 30 de octubre de 2017. Consultado el 4 de enero de 2018 .
  83. ^ "vibe.d - un conjunto de herramientas de alto rendimiento para aplicaciones web, concurrencia y E/S asíncronas escrito en D" . Consultado el 4 de enero de 2018 .
  84. ^ "Proyecto destacado: Diamond MVC Framework". 20 de noviembre de 2017. Consultado el 4 de enero de 2018 .
  85. ^ "Edad numérica para D: Mir GLAS es más rápido que OpenBLAS y Eigen" . Consultado el 4 de enero de 2018 .
  86. ^ "Sobre Tilix y D: una entrevista con Gerald Nunn". 11 de agosto de 2017. Consultado el 4 de enero de 2018 .
  87. ^ "Proyecto destacado: DlangUI". 7 de octubre de 2016. Consultado el 4 de enero de 2018 .
  88. ^ "Proyecto destacado: Funkwerk". 28 de julio de 2017. Consultado el 4 de enero de 2018 .
  89. ^ "Netflix/vectorflow". GitHub.com . Netflix, Inc. 5 de mayo de 2020 . Consultado el 7 de mayo de 2020 .
  90. ^ "Los piratas informáticos de Lazarus lanzan un nuevo malware RAT utilizando un error de Log4j de hace dos años". 11 de diciembre de 2023. Consultado el 11 de diciembre de 2023 .
  91. ^ "Ha zarpado un barco que transportaba plata" . Consultado el 6 de mayo de 2024 .
  92. ^ "El lenguaje de programación OpenD" . Consultado el 14 de mayo de 2024 .

Lectura adicional

  • Alexandrescu, Andrei (4 de enero de 2010). El lenguaje de programación D (1.ª edición). Addison-Wesley Professional. ISBN 978-0-321-63536-5.
  • Alexandrescu, Andrei (15 de junio de 2009). "El caso de D". Diario del Dr. Dobb.
  • Bright, Walter (8 de abril de 2014). "Cómo llegué a escribir D". Diario del Dr. Dobb.
  • Çehreli, Ali (1 de febrero de 2012). "Programación en D".(distribuido bajo licencia CC-BY-NC-SA). Este libro enseña programación a principiantes, pero también cubre muchos temas avanzados de D.
  • Metz, Cade (7 de julio de 2014). "El próximo gran lenguaje de programación del que nunca has oído hablar". Wired .
  • Ruppe, Adam (mayo de 2014). D Libro de cocina (1 ed.). Publicación PAQUETE. ISBN 978-1-783-28721-5.
  • Sitio web oficial
  • Marte digital
  • Foro Turco
  • Dlang en GitHub
Obtenido de "https://es.wikipedia.org/w/index.php?title=D_(lenguaje_de_programación)&oldid=1252979642"