D , también conocido como Dlang , es un lenguaje de programación de sistema de múltiples paradigmas 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 un idioma distinto. Ha rediseñado algunas características básicas de C ++, al tiempo que comparte características de otros lenguajes, en particular Java , Python , Ruby , C # y Eiffel .
Paradigma | Multi-paradigma : funcional , imperativo , orientado a objetos |
---|---|
Diseñada por | Walter Bright , Andrei Alexandrescu (desde 2007) |
Desarrollador | Fundación del Lenguaje D |
Apareció por primera vez | 8 de diciembre de 2001 [1] |
Lanzamiento estable | 2.096.0 [2] / 11 de marzo de 2021 |
Disciplina de mecanografía | Inferido , estático , fuerte |
SO | FreeBSD , Linux , macOS , Windows |
Licencia | Impulsar [3] [4] [5] |
Extensiones de nombre de archivo | .d [6] [7] |
Sitio web | dlang |
Implementaciones importantes | |
DMD ( implementación de referencia ), GCC , GDC , LDC , SDC | |
Influenciado por | |
C , C ++ , C # , Eiffel , [8] Java , Python | |
Influenciado | |
Genie , MiniD, Qore , Swift , [9] Vala , C ++ 11 , C ++ 14 , C ++ 17 , C ++ 20 , Go , C # y otros. | |
|
Los objetivos de diseño del lenguaje intentaron combinar el rendimiento y la seguridad de los lenguajes compilados con el poder expresivo de los lenguajes dinámicos modernos . El código D idiomático suele ser tan rápido como el código C ++ equivalente, aunque también es más corto. [10] El lenguaje en su conjunto no es seguro para la memoria [11] pero incluye atributos opcionales diseñados para verificar la seguridad de la memoria. [12]
La inferencia de tipos , la gestión automática de la memoria y el azúcar sintáctico para los tipos comunes permiten un desarrollo más rápido , mientras que la verificación de límites , las funciones de diseño por contrato y un sistema de tipos con reconocimiento de simultaneidad ayudan a reducir la aparición de errores . [13]
Características
D fue diseñado con lecciones aprendidas del uso práctico de C ++, en lugar de una perspectiva puramente teórica. Aunque el lenguaje usa muchos conceptos de C y C ++, también descarta algunos o usa diferentes enfoques (y sintaxis) para lograr algunos objetivos. Como tal, no es compatible con el código fuente (y no pretende serlo) con el código fuente C y C ++ en general (algunas bases de código más simples de estos lenguajes podrían, por suerte, funcionar con D, o requerir alguna adaptación ). Sin embargo, D se ha visto limitado en su diseño por la regla de que cualquier código que fuera legal tanto en C como en D debería comportarse de la misma manera. D obtuvo algunas características antes de C ++, como cierres , funciones anónimas , ejecución de funciones en tiempo de compilación , rangos, conceptos de iteración de contenedores incorporados e inferencia de tipos . D se suma a la funcionalidad de C ++ al implementar también diseño por contrato , pruebas unitarias , módulos verdaderos , recolección de basura , matrices de primera clase , matrices asociativas , matrices dinámicas , corte de matrices , funciones anidadas , evaluación diferida, ejecución de código con alcance (diferido) y una sintaxis de plantilla rediseñada . D conserva la capacidad de C ++ para realizar programación de bajo nivel y agregar ensamblador en línea . La herencia múltiple de C ++ fue reemplazada por la herencia única de estilo Java con interfaces y mixins . Por otro lado, la sintaxis de declaración, declaración y expresión de D se asemeja mucho a la de C ++.
El ensamblador en línea tipifica las diferencias entre D y lenguajes de aplicación como Java y C # . Un ensamblador en línea permite a los programadores ingresar código de ensamblaje específico de la máquina dentro del código D estándar, un método utilizado por los programadores del sistema para acceder a las funciones de bajo nivel del procesador necesarias para ejecutar programas que interactúan directamente con el hardware subyacente , como sistemas operativos y dispositivos. controladores , además de escribir código de alto rendimiento (es decir, usando extensiones vectoriales, SIMD ) que es difícil de generar automáticamente por el compilador.
D tiene soporte incorporado para comentarios de documentación, lo que permite la generación automática de documentación .
Paradigmas de programación
D admite cinco paradigmas de programación principales : imperativo , orientado a objetos , metaprogramación , funcional y concurrente ( modelo de actor ).
Imperativo
La programación imperativa en D es casi idéntica a la de C. Las funciones, los datos, las declaraciones, las declaraciones y las expresiones funcionan igual que en C, y se puede acceder directamente a la biblioteca de tiempo de ejecución de C. Por otro lado, algunas diferencias notables entre D y C en el área de programación imperativa incluyen la foreachconstrucción de bucle de D , que permite recorrer una colección, y funciones anidadas , que son funciones que se declaran dentro de otra y pueden acceder a las variables locales de la función envolvente. .
import std . stdio ; void main () { int multiplicador = 10 ; int escalado ( int x ) { retorno x * multiplicador ; } foreach ( i ; 0 .. 10 ) { writefln ( "¡Hola, mundo% d! escalado =% d" , i , escalado ( i )); } }
D también incluye matrices dinámicas y matrices asociativas de forma predeterminada en el lenguaje.
Los símbolos (funciones, variables, clases) se pueden declarar en cualquier orden; no se requieren declaraciones de reenvío . De manera similar, las importaciones se pueden realizar casi en cualquier orden, e incluso tener un alcance (es decir, importar algún módulo o parte de él dentro de una función, clase o prueba unitaria solamente).
D admite la sobrecarga de funciones .
Orientado a objetos
La programación orientada a objetos en D se basa en una única jerarquía de herencia, con todas las clases derivadas de la clase Object. D no admite herencia múltiple; en su lugar, utiliza interfaces de estilo Java , que son comparables a las clases abstractas puras de C ++, y mixins , que separa 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 tipos de devolución de métodos anulados.
D admite la sobrecarga del operador , el reenvío de tipos y el envío dinámico personalizado opcional .
Las clases (e interfaces) en D pueden contener invariantes que se comprueban automáticamente antes y después de la entrada a métodos públicos. Forma parte de la metodología de diseño por contrato .
Muchos aspectos de las clases (y estructuras) se pueden introspectar automáticamente en tiempo de compilación (una forma de reflexión usando type traits
) y en tiempo de ejecución (RTII / TypeInfo
), para facilitar el código genérico o la generación automática de código (generalmente usando técnicas de tiempo de compilación).
Metaprogramación
La metaprogramación es compatible con una combinación de plantillas, ejecución de funciones en tiempo de compilación, tuplas y combinaciones de cadenas. Los siguientes ejemplos demuestran algunas de las funciones 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:
ulong factorial ( ulong n ) { if ( n < 2 ) return 1 ; de lo contrario, devuelve n * factorial ( n - 1 ); }
Aquí, static if
se demuestra el uso de la construcción condicional en 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 ) enum Factorial = 1 ; else enumeración Factorial = n * Factorial ! ( n - 1 ); }
En los dos ejemplos siguientes, la plantilla y la función definidas anteriormente se utilizan para calcular factoriales. Los tipos de constantes no necesitan especificarse explícitamente ya que el compilador infiere sus tipos desde el lado derecho de las asignaciones:
enum fact_7 = Factorial ! ( 7 );
Este es un ejemplo de ejecución de una función en tiempo de compilación . Las funciones ordinarias se pueden usar en expresiones constantes en tiempo de compilación siempre que cumplan con ciertos criterios:
enum fact_9 = factorial ( 9 );
La std.string.format
función realiza printfcomo formateo de datos (también en tiempo de compilación, a través de CTFE ), y el pragma "msg" muestra el resultado en tiempo de compilación:
import std . cadena : formato ; pragma ( mensaje , formato ( "7! =% s" , fact_7 )); pragma ( mensaje , formato ( "9! =% s" , fact_9 ));
Las combinaciones de cadenas, combinadas con la ejecución de funciones en tiempo de compilación, permiten generar código D utilizando operaciones de cadena en tiempo de compilación. Esto se puede usar para analizar lenguajes específicos de dominio en código D, que se compilará 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" ))); }
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 . Hay dos sintaxis para las funciones anónimas, incluida una forma de declaración múltiple y una notación de expresión única "taquigráfica": [10]
int función ( int ) g ; g = ( x ) { retorno x * x ; }; // a mano g = ( x ) => x * x ; // taquigrafía
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 entorno circundante. La inferencia de tipos se puede utilizar con una función anónima, en cuyo caso el compilador crea una a delegate
menos que pueda probar que no es necesario un puntero de entorno. Del mismo modo, para implementar un cierre, el compilador coloca variables locales encerradas en el montón solo si es necesario (por ejemplo, si otra función devuelve un cierre y sale del alcance de esa función). Al usar la inferencia de tipos, el compilador también agregará atributos como pure
y nothrow
al tipo de una función, si puede probar que se aplican.
Otras características funcionales como el currying y funciones comunes de orden superior como mapear , filtrar y reducir están disponibles a través de los módulos de biblioteca estándar std.functional
y std.algorithm
.
import std . stdio , std . algoritmo , std . variar ;void main () { 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 el interior de una función pura inmutable pivot = 5 ; int mySum ( int a , int b ) pure nothrow // función pura { if ( b <= pivote ) // ref al alcance-envolvente return a + b ; si no, devuelve un ; } // pasando un delegado (cierre) resultado automático = ¡ reducir ! mySum ( cadena ( a1 , a2 )); Writeln ( "Resultado:" , resultado ); // Resultado: 15 // pasando un resultado literal delegado = ¡ reducir ! (( a , b ) => ( b <= pivote ) ? a + b : a ) ( cadena ( a1 , a2 )); Writeln ( "Resultado:" , resultado ); // Resultado: 15 }
Alternativamente, las composiciones de funciones anteriores se pueden expresar utilizando la sintaxis uniforme de llamadas a funciones (UFCS) para una lectura más natural de izquierda a derecha:
resultado automático = a1 . cadena ( a2 ). reducir ! mySum (); Writeln ( "Resultado:" , resultado ); resultado = a1 . cadena ( a2 ). reducir ! (( a , b ) => ( b <= pivote ) ? a + b : a ) (); Writeln ( "Resultado:" , resultado );
Paralelo
Los conceptos de programación paralela se implementan en la biblioteca y no requieren soporte adicional del compilador. Sin embargo, el compilador y el sistema de tipo D garantizan que el intercambio de datos se pueda detectar y gestionar de forma transparente.
import std . stdio : writeln ; import std . rango : iota ; import std . paralelismo : paralelo ;void main () { foreach ( i ; iota ( 11 ). paralelo ) { // El cuerpo del bucle foreach se ejecuta en paralelo para cada i writeeln ( "procesamiento" , i ); } }
iota(11).parallel
es equivalente a std.parallelism.parallel(iota(11))
usar UFCS.
El mismo módulo también admite taskPool
que se puede usar para la creación dinámica de tareas paralelas, así como operaciones de estilo de mapa-filtro-reducción y plegado en rangos (y matrices), lo cual es útil cuando se combina con operaciones funcionales:
import std . stdio : writeln ; import std . algoritmo : mapa ; import std . rango : iota ; import std . paralelismo : taskPool ;void main () { números automáticos = iota ( 1.0 , 1_000_000_000.0 ); auto x = taskPool . reducir ! "a + b" ( 0.0 , map ! "1.0 / (a * a)" ( nums ) ); Writeln ( "Suma:" , x ); // En Intel i7-3930X y gdc 9.3.0: // 5140ms usando std.algorithm.reduce // 888ms usando std.parallelism.taskPool.reduce; // En AMD Threadripper 2950X y gdc 9.3.0: // 2864ms usando std.algorithm.reduce // 95ms usando std.parallelism.taskPool.reduce }
Este código utiliza el hecho de que en std.algorithm.map
realidad no devuelve una matriz, sino un rango de evaluación perezosa, de esta manera los elementos reales del mapa son calculados por cada tarea de trabajo en paralelo de forma automática.
Concurrente
La programación concurrente está completamente implementada en la biblioteca y no requiere ningún soporte especial del compilador. Son posibles implementaciones y metodologías alternativas para escribir código concurrente. El uso del sistema de mecanografía D ayuda a garantizar la seguridad de la memoria.
import std . stdio , std . concurrencia , std . variante ;void foo () { bool cont = true ; while ( cont ) { recibir ( // Los delegados se utilizan para coincidir con el tipo de mensaje. ( int msg ) => writeln ( "int recibido:" , msg ), ( Tid sender ) { cont = false ; sender . send (- 1 ); }, ( Variant v ) => writeln ( "¿eh?" ) // La variante coincide con cualquier tipo ); } }void main () { auto tid = spawn (& foo ); // genera un nuevo hilo ejecutando foo () foreach ( i ; 0 .. 10 ) tid . enviar ( i ); // envía algunos enteros tid . enviar ( 1.0f ); // envía un tid flotante . enviar ( "hola" ); // envía una cadena tid . enviar ( thisTid ); // enviar una estructura (Tid) recibir (( int x ) => writeln ( "Mensaje recibido del hilo principal:" , x )); }
Gestión de la memoria
La memoria generalmente se administra con recolección de elementos no utilizados , pero los objetos específicos se pueden finalizar 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, la administración explícita de la memoria es posible utilizando los operadores sobrecargados new
y delete
, llamando a C 's malloc y free directamente, o implementando esquemas de asignación personalizados (es decir, en la pila con respaldo, asignación de estilo RAII, recuento de referencias, recuento 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. [14] El manual da muchos ejemplos de cómo implementar diferentes esquemas de administración de memoria altamente optimizados para cuando la recolección de basura es inadecuada en un programa. [15]
En las funciones, structs
se asignan de forma predeterminada en la pila, mientras que classes
de forma predeterminada se asignan 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, usando una plantilla de biblioteca estándar std.typecons.scoped
, o usando new
para estructuras y asignando un puntero en lugar de una variable basada en valores. [dieciséis]
En función, las matrices estáticas (de tamaño conocido) se asignan en la pila. Para matrices dinámicas, se puede usar la core.stdc.stdlib.alloca
función (similar a la función C alloca
, para asignar memoria en la pila. El puntero devuelto se puede usar (refundir) en una matriz dinámica (con tipo), por medio de un segmento (sin embargo, se debe cambiar el tamaño de la matriz, incluida la agregación). evitados; y por razones obvias no deben ser devueltos de la función). [17]
Se scope
puede usar una palabra clave para anotar partes del código, pero también variables y clases / estructuras, para indicar que deben ser destruidas (llamado destructor) inmediatamente al salir del alcance. Cualquiera que sea la memoria desasignada también depende de la implementación y de las diferencias entre clases y estructuras. [18]
std.experimental.allocator
contiene plantillas de asignadores modulares y componibles, para crear asignadores personalizados de alto rendimiento para casos de uso especiales. [19]
SafeD
SafeD [20] es el nombre que se le da al subconjunto de D que puede garantizarse como seguro para la memoria (no se escribe en la memoria que no se ha asignado o que se ha reciclado). Las funciones marcadas @safe
se comprueban en el momento de la compilación para garantizar que no utilicen ninguna característica que pueda dañar la memoria, como aritmética de punteros y conversiones no comprobadas, y cualquier otra función llamada también debe marcarse como @safe
o @trusted
. Las funciones se pueden marcar @trusted
para 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 caso potencial de corrupción de la memoria. [21]
Seguridad de por vida del alcance
Inicialmente bajo las banderas de DIP1000 [22] y DIP25 [23] (ahora parte de la especificación del lenguaje [24] ), D proporciona protecciones contra ciertas construcciones mal formadas que involucran la vida útil de los datos.
Los mecanismos actuales implementados se ocupan principalmente de los parámetros de función y la memoria de pila, sin embargo, es una ambición declarada del liderazgo del lenguaje de programación proporcionar un tratamiento más completo de las vidas dentro del lenguaje de programación D. [25] (Influenciado por ideas del lenguaje de programación Rust ).
Seguridad de por vida de las asignaciones
Dentro del código @safe, se verifica la vida útil de una asignación que involucra un tipo de referencia para garantizar que la vida útil 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 malo = 45 ; // El tiempo de vida de "malo" solo se extiende al ámbito en el que está definido. * rad = malo ; // Esto es kosher. rad = & malo ; // La vida útil de rad es más larga que mala, por lo tanto, esto no es kosher en absoluto. } }
Anotaciones de vida útil del parámetro 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 devuelven y el alcance restringen la vida útil y el uso de ese parámetro.
El estándar dicta el siguiente comportamiento: [26]
Clase de almacenamiento | Comportamiento (y restricciones a) de un parámetro con la clase de almacenamiento |
---|---|
alcance | las referencias en el parámetro no se pueden escapar. Ignorado para parámetros sin referencias |
regreso | El parámetro puede devolverse o copiarse al primer parámetro, pero de lo contrario no escapa de la función. Se requiere que dichas copias no sobrevivan a los argumentos de los que se derivaron. Ignorado para parámetros sin referencias |
A continuación se proporciona un ejemplo anotado.
@safe :int * gp ; Thorin vacío ( alcance int *); gloina vacía ( int *); int * balin ( retorno alcance int * p , alcance int * q , int * r ) { gp = p ; // error, p escapa a global gp gp = q ; // error, q escapa a global gp gp = r ; // OK thorin ( p ); // ok, p no escapa a thorin () thorin ( q ); // ok thorin ( r ); // OK gloina ( p ); // error, gloin () escapa de p gloin ( q ); // error, gloin () escapa q gloin ( r ); // ok esa gloin () escapa r return p ; // ok devuelve q ; // error, no se puede devolver 'alcance' q return r ; // ok }
Interacción con otros sistemas
C 's interfaz de aplicación binaria (ABI) es compatible, así como todos los tipos fundamentales y derivados de C, que permiten acceder directamente al código C y bibliotecas existentes. Los enlaces D están disponibles para muchas bibliotecas C populares. Además, la biblioteca estándar de C es parte del estándar D.
En Microsoft Windows, D puede acceder al código del Modelo de objetos componentes (COM).
Siempre que la gestión de la memoria se cuide adecuadamente, se pueden mezclar muchos otros lenguajes con D en un solo binario. Por ejemplo, el compilador GDC permite vincular C, C ++ y otros códigos de idiomas admitidos para que se mezclen. El código D (funciones) también se puede marcar para usar C, C ++, Pascal ABI y, por lo tanto, pasar a las bibliotecas escritas en estos lenguajes como devoluciones de llamada . Del mismo modo, los datos se pueden intercambiar entre los códigos escritos en estos idiomas de ambas formas. Esto generalmente restringe el uso a tipos primitivos, punteros, algunas formas de matrices, uniones, estructuras y solo algunos tipos de punteros de función.
Debido a que muchos otros lenguajes de programación a menudo proporcionan 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 C estándar (con un archivo de interfaz 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 de reflexión de tipos en tiempo de compilación.
Interacción con el código C ++
D adopta un enfoque permisivo pero realista para la interoperación con código C ++. [30]
Para el código D marcado como externo (C ++) , se especifican las siguientes características:
- Las convenciones de manipulación de nombres deben coincidir con las de C ++ en el destino.
- Para llamadas de función, la ABI será equivalente.
- La vtable debe 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 externa (C ++, espacio de nombres) donde espacio de nombres es el nombre del espacio de nombres de C ++.
Un ejemplo de interoperación de C ++
El lado de C ++
#include usando el espacio de nombres std ; class Base { public : virtual void print3i ( int a , int b , int c ) = 0 ; };clase Derivado : público Base { público : campo int ; Derivado ( campo int ) : campo ( campo ) {} void print3i ( int a , int b , int c ) { cout << "a =" << a << endl ; cout << "b =" << b << endl ; cout << "c =" << c << endl ; } int mul ( factor int ); };int Derivado :: mul ( factor int ) { campo de retorno * factor ; } Derived * createInstance ( int i ) { return new Derived ( i ); }anular deleteInstance ( Derivado * & d ) { eliminar d ; d = 0 ; }
El lado D
extern ( C ++) { clase abstracta Base { void print3i ( int a , int b , int c ); } clase Derivado : Base { campo int ; @disable this (); anular void print3i ( int a , int b , int c ); final int mul ( factor int ); } CreateInstance derivado ( int i ); anular deleteInstance ( ref Derived d ); }void main () { import std . stdio ; auto d1 = createInstance ( 5 ); Writeln ( campo d1 . ); escrito ( d1 . mul ( 4 )); Base b1 = d1 ; b1 . print3i ( 1 , 2 , 3 ); deleteInstance ( d1 ); afirmar ( d1 es nulo ); auto d2 = createInstance ( 42 ); Writeln ( campo d2 . ); deleteInstance ( d2 ); afirmar ( d2 es nulo ); }
Mejor C
El lenguaje de programación D tiene un subconjunto oficial conocido como " Better C ". [31] Este subconjunto prohíbe el acceso a funciones de D que requieren el uso de bibliotecas en tiempo de ejecución distintas 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 código compilado sin el Una mejor opción C puede llamar al código compilado con ella: esto, sin embargo, conducirá a comportamientos ligeramente diferentes debido a las diferencias en la forma en que C y D manejan las afirmaciones.
Funciones disponibles en el subconjunto Better C
- Uso sin restricciones de funciones en 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)
- Instalaciones completas de metaprogramación
- Funciones anidadas, estructuras anidadas, delegados y lambdas
- Funciones miembro, constructores, destructores, sobrecarga operativa, etc.
- El sistema de módulo completo
- Corte de matriz y comprobación de límites de matriz
- RAII
- alcance (salida)
- Protecciones de seguridad de la memoria
- Interfaz con C ++
- Clases COM y clases C ++
- Las fallas de aserción se dirigen a la biblioteca de tiempo de ejecución de C
- interruptor con cuerdas
- interruptor final
- bloques unittest
- validación del formato printf
- Recolección de basura
- TypeInfo y ModuleInfo
- Roscado integrado (p
core.thread
. Ej. ) - Matrices dinámicas (aunque las porciones de matrices estáticas funcionan) y matrices asociativas
- Excepciones
- sincronizado y
core.sync
- Constructores o destructores de módulos estáticos
Historia
Walter Bright comenzó a trabajar en un nuevo lenguaje en 1999. D fue lanzado por primera vez en diciembre de 2001 [1] y alcanzó la versión 1.0 en enero de 2007. [32] La primera versión del lenguaje (D1) se concentró en el imperativo, la orientación a objetos y la metaprogramación. paradigmas, [33] similar a C ++.
Algunos miembros de la comunidad D insatisfechos con Phobos, el tiempo de ejecución oficial y la biblioteca estándar de D , crearon un tiempo de ejecución alternativo y una biblioteca estándar llamada Tango. El primer anuncio público de Tango se produjo pocos días después del lanzamiento de D 1.0. [34] Tango adoptó un estilo de programación diferente, adoptando la programación orientada a objetos y una alta modularidad. Al ser un proyecto liderado por la comunidad, Tango estaba más abierto a 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 diferentes API de soporte de tiempo 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 de uso generalizado, ha dado lugar a una disputa importante debido a que algunos paquetes usan Phobos y otros usan Tango. [35]
En junio de 2007, se lanzó la primera versión de D2. [36] El comienzo del desarrollo de D2 marcó la estabilización de D1. La primera versión del lenguaje se ha puesto en mantenimiento, solo ha recibido correcciones y correcciones de errores de implementación. D2 introdujo cambios importantes en el lenguaje, comenzando con su primer sistema de const experimental . Posteriormente, 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ó los problemas de la biblioteca estándar al separar el tiempo de ejecución de la biblioteca estándar. La finalización de un puerto D2 Tango se anunció en febrero de 2012. [37]
El lanzamiento del libro de Andrei Alexandrescu The D Programming Language el 12 de junio de 2010, marcó la estabilización de D2, que en la actualidad se conoce comúnmente como simplemente "D".
En enero de 2011, el desarrollo de D pasó de una base de seguimiento de errores / envío de parches a GitHub . Esto ha dado lugar a un aumento significativo de las contribuciones al compilador, el tiempo de ejecución y la biblioteca estándar. [38]
En diciembre de 2011, Andrei Alexandrescu anunció que D1, la primera versión del lenguaje, se suspendería el 31 de diciembre de 2012. [39] La versión final de D1, D v1.076, fue el 31 de diciembre de 2012. [40]
El código para el compilador D oficial, el compilador Digital Mars D de Walter Bright, fue lanzado originalmente bajo una licencia personalizada , calificando como fuente disponible pero no conforme a la definición de fuente abierta . [41] En 2014, el front-end del compilador se volvió a licenciar como código abierto bajo la licencia de software Boost . [3] Este código de nueva licencia excluyó el back-end, que había sido desarrollado parcialmente en Symantec . El 7 de abril de 2017, todo el compilador estuvo disponible bajo la licencia de Boost después de que Symantec otorgó permiso para volver a licenciar el back-end también. [4] [42] [43] [44] El 21 de junio de 2017, se aceptó la inclusión del Lenguaje D en GCC. [45]
A partir de GCC 9, GDC (abreviatura de GNU D Compiler o GCC D Compiler), una interfaz de lenguaje D basada en la interfaz de código abierto DMD se fusionó con GCC. [46]
Implementaciones
La mayoría de las implementaciones actuales de D se compilan directamente en código de máquina para una ejecución eficiente.
Compiladores listos para producción:
- DMD : el compilador Digital Mars D de Walter Bright es el compilador D oficial; de código abierto bajo la licencia de software Boost . [3] [4] La interfaz DMD es compartida por GDC (ahora en GCC) y LDC, para mejorar la compatibilidad entre compiladores. Inicialmente, la interfaz se escribió 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 de Symantec. Al principio, solo admitía x86 de 32 bits, con soporte agregado para amd64 de 64 bits y PowerPC de Walter Bright. Más tarde, el backend y casi todo el compilador se transfirieron de C ++ a D para un autohospedaje completo.
- GCC - The GNU Compiler Collection , fusionó GDC [47] en GCC 9 el 2018-10-29. [48] Las primeras versiones de trabajo de GDC con GCC, basadas en GCC 3.3 y GCC 3.4 en x86 de 32 bits en Linux y Mac OS X [49] se publicaron el 22 de marzo de 2004. Desde entonces, GDC ganó soporte para más plataformas, y mejoró el rendimiento y corrigió errores, mientras rastreaba el código DMD ascendente para la interfaz y la especificación del idioma.
- LDC : un compilador basado en el front-end DMD que usa LLVM como su back-end del compilador. La primera versión con calidad de lanzamiento se publicó el 9 de enero de 2009. [50] Es compatible con la versión 2.0. [51]
Compiladores de juguete y de prueba de concepto:
- Compilador D para .NET : un back-end para el compilador del lenguaje de programación D 2.0. [52] [53] Compila el código en código de bytes de Lenguaje Intermedio Común (CIL) en lugar de código de máquina. Luego, el CIL se puede ejecutar a través de una máquina virtual de Common Language Infrastructure (CLI) . El proyecto no se ha actualizado en años y el autor indicó que el proyecto ya no está activo.
- SDC : el compilador Stupid D utiliza un front-end personalizado y LLVM como su back-end del compilador. Está escrito en D y usa un programador para manejar la resolución de símbolos con el fin de manejar elegantemente las características de tiempo de compilación de D. Este compilador actualmente soporta 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, incluidas x86 , amd64 , AArch64 , PowerPC , MIPS64 , DEC Alpha , Motorola m68k , Sparc , s390 , WebAssembly . Los principales sistemas operativos compatibles son Windows y Linux , pero varios compiladores también admiten Mac OS X , FreeBSD , NetBSD , AIX , Solaris / OpenSolaris y Android , ya sea como host o destino, o ambos. El destino de WebAssembly (compatible a través de LDC y LLVM) puede funcionar en cualquier entorno de WebAssembly, como un 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 D incluyen Eclipse , Microsoft Visual Studio , SlickEdit , Emacs , vim , SciTE , Smultron , TextMate , MonoDevelop , Zeus, [56] y Geany, entre otros. [57]
- Dexed (antes Coedit) [58] un IDE gráfico centrado en D escrito en Object Pascal
- Mono-D [59] es un IDE gráfico multiplataforma basado en MonoDevelop / Xamarin Studio, escrito principalmente en C # .
- Los complementos de Eclipse para D incluyen: DDT [60] y Descent (proyecto muerto). [61]
- VisualD proporciona la integración de Visual Studio. [62] [63]
- Integración de Visual Studio Code con extensiones como Dlang-Vscode [64] o Code-D. [sesenta y cinco]
- Vim admite tanto el resaltado de sintaxis como la finalización de código
- Hay un paquete disponible para TextMate y Code :: Blocks IDE incluye soporte parcial para el idioma. Sin embargo, las características estándar de IDE como la finalización de código o la refactorización aún no están disponibles, aunque funcionan parcialmente en Code :: Blocks (debido a la similitud de D con C).
- Hay disponible un complemento para Xcode 3 , D para Xcode, para habilitar proyectos y desarrollo basados en D. [66]
- Hay disponible un complemento para MonoDevelop, denominado Mono-D. [67]
- El complemento de autocompletado de KDevelop (así como su editor de texto, Kate) está disponible. [68]
Además, muchos otros editores e IDE admiten el resaltado de sintaxis y la finalización parcial de código / identificador para D.
Existen IDE D de código abierto para Windows , algunos escritos en D, como Poseidon, [69] D-IDE, [70] y Entice Designer. [71]
Las aplicaciones D se pueden depurar utilizando cualquier depurador C / C ++, como GDB o WinDbg , aunque la compatibilidad con varias funciones de lenguaje específicas de D es extremadamente limitada. En Windows, los programas D se pueden depurar usando Ddbg , o las herramientas de depuración de Microsoft (WinDBG y Visual Studio), después de haber convertido la información de depuración usando cv2pdb . El depurador ZeroBUGS para Linux tiene soporte experimental para el lenguaje D. Ddbg se puede utilizar con varios IDE o desde la línea de comandos; ZeroBUGS tiene su propia interfaz gráfica de usuario (GUI).
Un DustMite es una herramienta poderosa para minimizar el código fuente D, útil cuando se encuentran problemas con el compilador o las pruebas. [72]
dub es un paquete popular y un administrador de compilación para aplicaciones y bibliotecas D, y a menudo está integrado en el soporte de IDE. [73]
Ejemplos de
Ejemplo 1
Este programa de ejemplo imprime sus argumentos de línea de comando. La main
función es el punto de entrada de un programa D y args
es una matriz de cadenas que representan los argumentos de la línea de comandos. A string
en D es una matriz de caracteres, representada por immutable(char)[]
.
import std . stdio : writefln ;void main ( string [] args ) { foreach ( i , arg ; args ) writefln ( "args [% d] = '% s'" , i , arg );}
La foreach
declaración puede iterar sobre cualquier colección. En este caso, está produciendo una secuencia de índices ( i
) y valores ( arg
) de la matriz args
. El índice i
y el valor arg
tienen sus tipos inferidos del tipo de la matriz args
.
Ejemplo 2
A continuación se muestran varias capacidades D y compensaciones de diseño D en un programa corto. Repite las líneas de un archivo de texto denominado words.txt
, que contiene una palabra diferente en cada línea, e imprime todas las palabras que son anagramas de otras palabras.
import std . stdio , std . algoritmo , std . rango , std . cadena ;void main () { dstring [] [ dstring ] signature2words ; foreach ( dchar [] w ; líneas ( Archivo ( "palabras.txt" ))) { w = w . chomp (). toLower (); firma inmutable = w . dup . sort (). liberación (). idup ; signature2words [ firma ] ~ = w . idup ; } foreach ( palabras ; firma2palabras ) { if ( palabras . longitud > 1 ) { Writeln ( palabras . join ( "" )); } }}
signature2words
es una matriz asociativa incorporada que asigna claves dstring (32 bits / char) a matrices de dstrings. Es similar a ladefaultdict(list)
de Python .lines(File())
produce líneas perezosamente, con el salto de línea. Luego, debe copiarse conidup
para obtener una cadena que se utilizará para los valores de la matriz asociativa (laidup
propiedad de las matrices devuelve un duplicado inmutable de la matriz, que se requiere ya que eldstring
tipo es realmenteimmutable(dchar)[]
). Los arreglos asociativos incorporados requieren claves inmutables.- El
~=
operador agrega un nuevo dstring a los valores de la matriz dinámica asociada. toLower
,join
ychomp
son 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. LostoLower
convierte una cadena a minúsculas,join(" ")
se une a una matriz de cadenas en una sola cadena usando un único espacio como separador, ychomp
elimina un salto de línea desde el extremo de la cadena si uno está presente. Elw.dup.sort().release().idup
es más fácil de leer, pero equivalente arelease(sort(w.dup)).idup
, por 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 escritura de código como este a menudo se hace referencia como canalización (especialmente cuando los objetos utilizados se calculan de forma perezosa, por ejemplo, iteradores / rangos) o interfaz fluida .- El
sort
es una función std.algorithm que ordena la matriz en su lugar, la creación de una firma única para las palabras que son anagramas entre sí. Elrelease()
método del valor de retorno desort()
es útil para mantener el código como una sola expresión. - El segundo
foreach
itera sobre los valores de la matriz asociativa, es capaz de inferir el tipo dewords
. signature
se asigna a una variable inmutable, se infiere su tipo.-
dchar[]
Se utiliza UTF-32 en lugar del UTF-8 normal ; de lochar[]
contrario, sesort()
niega a clasificarlo. Hay formas más eficientes de escribir este programa usando solo UTF-8.
Usos
Las organizaciones notables que utilizan el lenguaje de programación D para proyectos incluyen Facebook , [74] eBay , [75] y Netflix . [76]
D se ha utilizado con éxito para juegos AAA , [77] intérpretes de idiomas, máquinas virtuales, [78] [79] un núcleo de sistema operativo , [80] programación de GPU , [81] desarrollo web , [82] [83] análisis numérico , [84] Aplicaciones GUI , [85] [86] un sistema de información para pasajeros , [87] aprendizaje automático, [88] procesamiento de texto, servidores web y de aplicaciones e investigación.
Ver también
- Ddoc
- Fundación del Lenguaje D
Referencias
- ^ a b "D Cambiar registro al 7 de noviembre de 2005" . D Lenguaje de programación 1.0 . Marte digital . Consultado el 1 de diciembre de 2011 .
- ^ "Cambio de registro: 2.096.0" . Consultado el 11 de marzo de 2021 .
- ^ a b c "dmd front end ahora cambió a licencia Boost" . Consultado el 9 de septiembre de 2014 .
- ^ a b c "dmd Backend convertido a Boost License" . El 7 de abril de 2017 . Consultado el 9 de abril de 2017 .
- ^ "Preguntas frecuentes sobre D 2.0" . Consultado el 11 de agosto de 2015 .
- ^ " " Lenguaje de programación D - Fileinfo.com " " . Consultado el 15 de noviembre de 2020 .[ cita requerida ]
- ^ " " Lenguaje de programación D - dlang.org " " . Consultado el 15 de noviembre de 2020 .[ cita requerida ]
- ^ Alexandrescu, Andrei (2010). El lenguaje de programación D (Primera ed.). Upper Saddle River, Nueva Jersey: Addison-Wesley. pag. 314 . ISBN 978-0321635365.
- ^ "Construcción de assert () en Swift, Parte 2: __FILE__ y __LINE__" . Consultado el 25 de septiembre de 2014 .
- ^ a b "Expresiones" . Marte digital . Consultado el 27 de diciembre de 2012 .
- ^ "En: cavilaciones sobre D: una entrevista con Walter Bright" . Noticias de hackers . 30 de agosto de 2016. "Está cerca y estamos trabajando para cerrar las brechas restantes".
- ^ "Memory-Safe-D-Spec" . Fundación de la Lengua D.
- ^ Andrei Alexandrescu (2 de agosto de 2010). Tres enfriar las cosas Acerca de D .
- ^ "std.gc" . D Lenguaje de programación 1.0 . Marte digital . Consultado el 6 de julio de 2010 .
- ^ "Gestión de la memoria" . D Lenguaje de programación 2.0 . Marte digital . Consultado el 17 de febrero de 2012 .
- ^ "Siga su propio camino (parte uno: la pila)" . El D Blog . Consultado el 7 de mayo de 2020 .
- ^ "Siga su propio camino (parte uno: la pila)" . El D Blog . Consultado el 7 de mayo de 2020 .
- ^ "Atributos - Lenguaje de programación D" . dlang.org . Consultado el 7 de mayo de 2020 .
- ^ "std.experimental.allocator - Lenguaje de programación D" . dlang.org . Consultado el 7 de mayo de 2020 .
- ^ Bartosz Milewski. "Lenguaje de programación SafeD - D" . Consultado el 17 de julio de 2014 .
- ^ Steven Schveighoffer (28 de septiembre de 2016). "Cómo escribir @trusted Code en D" . Consultado el 4 de enero de 2018 .
- ^ "Punteros con alcance" . 3 de abril de 2020.
- ^ "Referencias selladas" .
- ^ "Especificación del lenguaje D: Funciones - Parámetros de alcance de retorno" .
- ^ "Propiedad y Préstamo en D" . 15 de julio de 2019.
- ^ "Especificación del lenguaje D: Funciones - Clases de almacenamiento de parámetros de función" .
- ^ "PyD" . 7 de mayo de 2020 . Consultado el 7 de mayo de 2020 .
- ^ Parker, Mike. "Paquete abandonado-lua en DUB" . Registro de paquetes DUB . Consultado el 7 de mayo de 2020 .
- ^ Parker, Mike. "Paquete bindbc-lua en DUB" . Registro de paquetes DUB . Consultado el 7 de mayo de 2020 .
- ^ "Interfaz con C ++" .
- ^ "Mejor C" .
- ^ "D Cambio de registro" . D Lenguaje de programación 1.0 . Marte digital . Consultado el 11 de enero de 2012 .
- ^ "Introducción" . D Lenguaje de programación 1.0 . Marte digital . Consultado el 1 de diciembre de 2011 .
- ^ "Anuncio de una nueva biblioteca" . Consultado el 15 de febrero de 2012 .
- ^ "Wiki4D: Standard Lib" . Consultado el 6 de julio de 2010 .
- ^ "Cambiar registro - Lenguaje de programación D" . D Lenguaje de programación 2.0 . Fundación Idioma D . Consultado el 22 de noviembre de 2020 .
- ^ "Tango para D2: todos los módulos de usuario portados" . Consultado el 16 de febrero de 2012 .
- ^ Walter Bright. "Re: ¿GitHub o dsource?" . Consultado el 15 de febrero de 2012 .
- ^ Andrei Alexandrescu. "D1 se descontinuará el 31 de diciembre de 2012" . Consultado el 31 de enero de 2014 .
- ^ "D Cambio de registro" . D Lenguaje de programación 1.0 . Marte digital . Consultado el 31 de enero de 2014 .
- ^ "backendlicense.txt" . Código fuente DMD . GitHub. Archivado desde el original el 22 de octubre de 2016 . Consultado el 5 de marzo de 2012 .
- ^ "Comentario de Reddit por Walter Bright" . Consultado el 9 de septiembre de 2014 .
- ^ D-Compiler-unter-freier- Lizenz en linux-magazin.de (2017, en alemán)
- ^ cambie el backend a Boost License # 6680 de Walter Bright en github.com
- ^ D Idioma aceptado para su inclusión en GCC
- ^ "Cambios, nuevas funciones y correcciones de la serie de versiones GCC 9" .
- ^ "GDC" .
- ^ "GCC 9 Release Series - Cambios, nuevas características y correcciones - Proyecto GNU - Free Software Foundation (FSF)" . gcc.gnu.org . Consultado el 7 de mayo de 2020 .
- ^ "Otra interfaz para GCC" . forum.dlang.org . Consultado el 7 de mayo de 2020 .
- ^ "Proyecto del compilador LLVM D en GitHub" . Consultado el 19 de agosto de 2016 .
- ^ "BuildInstructionsPhobosDruntimeTrunk - ldc - Lenguaje de programación D - Trac" . Consultado el 11 de agosto de 2015 .
- ^ "Proyecto D .NET en CodePlex" . Consultado el 3 de julio de 2010 .
- ^ Jonathan Allen (15 de mayo de 2009). "La fuente para el compilador D.NET ya está disponible" . InfoQ . Consultado el 6 de julio de 2010 .
- ^ "DConf 2014: SDC, un compilador D como biblioteca de Amaury Sechet" . Consultado el 8 de enero de 2014 .
- ^ "deadalnix / SDC" . Consultado el 8 de enero de 2014 .
- ^ "Wiki4D: EditorSupport / ZeusForWindows" . Consultado el 11 de agosto de 2015 .
- ^ "Wiki4D: Soporte de editor" . Consultado el 3 de julio de 2010 .
- ^ "Basile.B / dexed" . GitLab . Consultado el 29 de abril de 2020 .
- ^ "Mono-D - D Wiki" . wiki.dlang.org . Consultado el 30 de abril de 2020 .
- ^ "Alojamiento de proyectos de Google" . Consultado el 11 de agosto de 2015 .
- ^ "descenso" . Consultado el 11 de agosto de 2015 .
- ^ "Lenguaje de programación Visual D - D" . Consultado el 11 de agosto de 2015 .
- ^ 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 .
- ^ "dlang-vscode" . Consultado el 21 de diciembre de 2016 .
- ^ "código-d" . Consultado el 21 de diciembre de 2016 .
- ^ "Michel Fortin - D para Xcode" . Consultado el 11 de agosto de 2015 .
- ^ "Soporte Mono-D - D para MonoDevelop" . Consultado el 11 de agosto de 2015 .
- ^ "Dav1dde / lumen" . GitHub . Consultado el 11 de agosto de 2015 .
- ^ "Poseidón" . Consultado el 11 de agosto de 2015 .
- ^ "Soporte Mono-D - D para MonoDevelop" . Consultado el 11 de agosto de 2015 .
- ^ "Entice Designer - Dprogramming.com - El lenguaje de programación D" . Consultado el 11 de agosto de 2015 .
- ^ "¿Qué es DustMite?" . Consultado el 29 de abril de 2020 .
- ^ "dlang / dub: sistema de gestión de paquetes y compilación para D" . Consultado el 29 de abril de 2020 .
- ^ "Under the Hood: warp, un preprocesador rápido de C y C ++" . 28 de marzo de 2014 . Consultado el 4 de enero de 2018 .
- ^ "Herramientas de línea de comandos más rápidas en D" . 24 de mayo de 2017 . Consultado el 4 de enero de 2018 .
- ^ "Presentación de Vectorflow" . El 2 de agosto de 2017 . Consultado el 4 de enero de 2018 .
- ^ "Quantum Break: juegos AAA con algún código D" . Consultado el 4 de enero de 2018 .
- ^ "Máquina virtual JavaScript de Higgs" . Consultado el 4 de enero de 2018 .
- ^ "Implementación AD del lenguaje de programación ECMA 262 (Javascript)" . Consultado el 4 de enero de 2018 .
- ^ "Proyecto destacado: el núcleo de PowerNex" . Consultado el 4 de enero de 2018 .
- ^ "DCompute: Ejecutando D en la GPU" . 30 de octubre de 2017 . Consultado el 4 de enero de 2018 .
- ^ "vibe.d: un kit de herramientas de aplicaciones web, concurrencia y E / S asíncronas de alto rendimiento escrito en D" . Consultado el 4 de enero de 2018 .
- ^ "Proyecto destacado: Diamond MVC Framework" . 20 de noviembre de 2017 . Consultado el 4 de enero de 2018 .
- ^ "Edad numérica para D: Mir GLAS es más rápido que OpenBLAS y Eigen" . Consultado el 4 de enero de 2018 .
- ^ "Sobre Tilix y D: una entrevista con Gerald Nunn" . 11 de agosto de 2017 . Consultado el 4 de enero de 2018 .
- ^ "Proyecto destacado: DlangUI" . Consultado el 4 de enero de 2018 .
- ^ "Proyecto destacado: Funkwerk" . Consultado el 4 de enero de 2018 .
- ^ "Netflix / vectorflow" . GitHub.com . Netflix, Inc.5 de mayo de 2020 . Consultado el 7 de mayo de 2020 .
Otras lecturas
- Alexandrescu, Andrei (4 de enero de 2010). El lenguaje de programación D (1 ed.). 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 D avanzados.
- Metz, Cade (7 de julio de 2014). "El próximo gran lenguaje de programación del que nunca ha oído hablar" . Cableado .
- Ruppe, Adam (mayo de 2014). D Recetario (1 ed.). Publicación PACKT. ISBN 978-1-783-28721-5.
enlaces externos
- Página web oficial
- Marte digital
- Foro turco
- Dlang en GitHub