X-Git-Url: https://git.llucax.com/z.facultad/75.00/informe.git/blobdiff_plain/e06143e98714199eba6570381554d812fd86556d..8554af7b6c3350a7bd644661868b38aa4fdb924e:/source/d.rst diff --git a/source/d.rst b/source/d.rst index 15334bd..f3f90db 100644 --- a/source/d.rst +++ b/source/d.rst @@ -15,27 +15,25 @@ Historia ---------------------------------------------------------------------------- D_ es un lenguaje de programación relativamente joven. Nació en 1999 y el -2 de enero de 2007 salió su `versión 1.0`__. Poco tiempo después se -continúo el desarrollo del lenguaje en la `versión 2.0`__, aún inestable -y en la cual se está experimentando principalmente sobre -multi-procesamiento. +2 de enero de 2007 salió su `versión 1.0`__. Poco tiempo después se continúo +el desarrollo del lenguaje en la `versión 2.0`__, aún inestable y en la cual +se está experimentando principalmente sobre multi-procesamiento. __ `D 1.0`_ __ `D 2.0`_ El lenguaje fue diseñado e implementado por `Walter Bright`_, desarrollador -principal de Zortech C++, uno de los primeros compilador de C++ que -compilaba a código nativo, y está fuertemente influenciado éste. Sin -embargo toma muchos conceptos de otros lenguajes de más alto nivel, como -Java_ o incluso lenguajes dinámicos como Perl_. +principal de Zortech C++, uno de los primeros compilador de C++ que compilaba +a código nativo, y está fuertemente influenciado éste. Sin embargo toma muchos +conceptos de otros lenguajes de más alto nivel, como Java_ o incluso lenguajes +dinámicos como Perl_. El origen del lenguaje está plasmado en su sitio web, en donde se cita: - It seems to me that most of the "new" programming languages fall into - one of two categories: Those from academia with radical new paradigms - and those from large corporations with a focus on RAD and the web. Maybe - it's time for a new language born out of practical experience - implementing compilers. + It seems to me that most of the "new" programming languages fall into one + of two categories: Those from academia with radical new paradigms and those + from large corporations with a focus on RAD and the web. Maybe it's time + for a new language born out of practical experience implementing compilers. Esto podría traducirse como: @@ -45,79 +43,75 @@ Esto podría traducirse como: y web. Tal vez es hora de que nazca un nuevo lenguaje de la experiencia práctica implementando compiladores. -La versión 1.0 fue más bien una etiqueta arbitraria que un indicador real -de estar ante una versión estable y completa. Luego de liberarse se -siguieron agregando nuevas características al lenguaje hasta que se empezó -el desarrollo en paralelo de la versión 2.0 al introducirse el concepto de -inmutabilidad y funciones *puras* [#dpure]_ (a mediados de 2007). +La versión 1.0 fue más bien una etiqueta arbitraria que un indicador real de +estar ante una versión estable y completa. Luego de liberarse se siguieron +agregando nuevas características al lenguaje hasta que se empezó el desarrollo +en paralelo de la versión 2.0 al introducirse el concepto de inmutabilidad +y funciones *puras* [#dpure]_ (a mediados de 2007). .. [#dpure] Por funciones *puras* en D_ se entiende que no tienen efectos - colaterales. Es decir, una función pura siempre que se llame con la - misma entrada producirá el mismo resultado. Esto es análogo a como - funcionan los lenguajes funcionales en general, abríendo la puerta a la - programación de estilo funcional en - D_. + colaterales. Es decir, una función pura siempre que se llame con la misma + entrada producirá el mismo resultado. Esto es análogo a como funcionan los + lenguajes funcionales en general, abríendo la puerta a la programación de + estilo funcional en D_. A partir de este momento la versión 1.0 quedó *teóricamente* congelada, -introduciendo solo cambios que arreglen errores (*bug fixes*), -introduciendo todos las nuevas características solamente en la versión -2.0 del lenguaje. La realidad es que se hicieron cambios incompatibles a la -versión 1.0 del lenguaje en reiteradas ocasiones, pero se fue tendiendo -a cada vez introducir menos cambios incompatibles. Sin embargo al día de -hoy el compilador de referencia sigue teniendo algunas características -presentes en la especificación del lenguaje sin implementar, por lo que -todavía no hay una implementación completa de la versión 1.0 del lenguaje, -siendo esta etiqueta todavía un poco arbitraria. +introduciendo solo cambios que arreglen errores (*bug fixes*), introduciendo +todos las nuevas características solamente en la versión 2.0 del lenguaje. La +realidad es que se hicieron cambios incompatibles a la versión 1.0 del +lenguaje en reiteradas ocasiones, pero se fue tendiendo a cada vez introducir +menos cambios incompatibles. Sin embargo al día de hoy el compilador de +referencia sigue teniendo algunas características presentes en la +especificación del lenguaje sin implementar, por lo que todavía no hay una +implementación completa de la versión 1.0 del lenguaje, siendo esta etiqueta +todavía un poco arbitraria. El lenguaje ha sido, hasta el desarrollo de la versión 2.0 al menos, un esfuerzo unipersonal de `Walter Bright`_, dados sus problemas a la hora de -delegar o aceptar contribuciones. Esto motivó a la comunidad de usuarios de -D_ a crear bibliotecas base alternativas a la estándar (llamada Phobos_) en -las cuales se pudiera trabajar sin las trabas impuestas por el autor del -lenguaje. +delegar o aceptar contribuciones. Esto motivó a la comunidad de usuarios de D_ +a crear bibliotecas base alternativas a la estándar (llamada Phobos_) en las +cuales se pudiera trabajar sin las trabas impuestas por el autor del lenguaje. En este contexto nacen primero Mango_ y luego Ares_. Mango_ fue creada por Kris Macleod Bell a principios de 2004 como una biblioteca que provee -servicios básicos de entrada/salida (o *I/O* de *input/output* en inglés) -de alto rendimiento. Siendo estos servicios algo básico lo más natural -hubiera sido que se encuentren en la biblioteca estándar de D_ pero por las +servicios básicos de entrada/salida (o *I/O* de *input/output* en inglés) de +alto rendimiento. Siendo estos servicios algo básico lo más natural hubiera +sido que se encuentren en la biblioteca estándar de D_ pero por las dificultades para contribuir a ésta, se desarrolla como una biblioteca separada. A mediados de 2004 Sean Kelly crea Ares_ , con las mismas -motivaciones pero con la intención de crear una biblioteca base (conocida -en inglés como *runtime*) que incluye los servicios básicos que necesita el +motivaciones pero con la intención de crear una biblioteca base (conocida en +inglés como *runtime*) que incluye los servicios básicos que necesita el lenguaje (información de tipos, manejo de excepciones e hilos, creación y manipulación de objetos, recolector de basura, etc.). Al poco tiempo de liberarse Ares_, Mango_ empieza a utilizarla como biblioteca base. -Para comienzos de 2006, se empieza a trabajar en la combinación de -ambas bibliotecas para lograr una biblioteca estándar alternativa -con un alto grado de cohesión. Finalmente a principios de 2007, -coincidiendo por casualidad con la aparición de D_ 1.0, se anuncia el -resultado de este combinación bajo el nombre de Tango_, proveyendo una -alternativa completa y madura a la biblioteca estándar de D_ Phobos_. -A principios de 2008 los principales desarrolladores de Tango_ (Kris Bell, -Sean Kelly, Lars Ivar Igesund y Michael Parker publican el libro llamado -`Learn to Tango with D`_. - -Esto por un lado fue un gran avance porque dio un impulso muy considerable -al lenguaje pero por otro un gran retroceso, porque todavía al día de hoy -D_ 1.0 tiene 2 bibliotecas base, una estándar pero de peor calidad y menos -mantenida y una alternativa de mayor calidad y apertura a la comunidad -(pero no estándar). El peor problema es que ambas son **incompatibles**, -por lo que un programa hecho con Tango_ no funciona con Phobos_ y viceversa -(a menos que el programador haya invertido una cantidad de tiempo no -trivial en asegurarse de que funcione con ambas). +Para comienzos de 2006, se empieza a trabajar en la combinación de ambas +bibliotecas para lograr una biblioteca estándar alternativa con un alto grado +de cohesión. Finalmente a principios de 2007, coincidiendo por casualidad con +la aparición de D_ 1.0, se anuncia el resultado de este combinación bajo el +nombre de Tango_, proveyendo una alternativa completa y madura a la biblioteca +estándar de D_ Phobos_. A principios de 2008 los principales desarrolladores +de Tango_ (Kris Bell, Sean Kelly, Lars Ivar Igesund y Michael Parker publican +el libro llamado `Learn to Tango with D`_. + +Esto por un lado fue un gran avance porque dio un impulso muy considerable al +lenguaje pero por otro un gran retroceso, porque todavía al día de hoy D_ 1.0 +tiene 2 bibliotecas base, una estándar pero de peor calidad y menos mantenida +y una alternativa de mayor calidad y apertura a la comunidad (pero no +estándar). El peor problema es que ambas son **incompatibles**, por lo que un +programa hecho con Tango_ no funciona con Phobos_ y viceversa (a menos que el +programador haya invertido una cantidad de tiempo no trivial en asegurarse de +que funcione con ambas). Esto hace que la compatibilidad de programas y bibliotecas esté muy -fragmentada entre las 2 bibliotecas base. Si bien no parece que vaya -a haber solución alguna a este problema para D 1.0, D 2.0 va en camino -a solucionar este problema ya que utiliza DRuntime_, un nuevo intento de -Sean Kelly por proveer una biblioteca *runtime* bien organizada -y mantenida, que es una adaptación de la biblioteca *runtime* de Tango_ -a D 2.0. Si bien todavía Tango_ no fue adaptada a D 2.0, se espera que -cuando esto pase compartan la misma biblioteca *runtime* permitiendo que -bibliotecas y programas hechos para Tango_ y Phobos_ 2.0 puedan coexistir -sin problemas. +fragmentada entre las 2 bibliotecas base. Si bien no parece que vaya a haber +solución alguna a este problema para D 1.0, D 2.0 va en camino a solucionar +este problema ya que utiliza DRuntime_, un nuevo intento de Sean Kelly por +proveer una biblioteca *runtime* bien organizada y mantenida, que es una +adaptación de la biblioteca *runtime* de Tango_ a D 2.0. Si bien todavía +Tango_ no fue adaptada a D 2.0, se espera que cuando esto pase compartan la +misma biblioteca *runtime* permitiendo que bibliotecas y programas hechos para +Tango_ y Phobos_ 2.0 puedan coexistir sin problemas. Descripción general @@ -126,28 +120,28 @@ Descripción general D_ es un lenguaje de programación con sintaxis tipo C, multi-paradigma, compilado, con *tipado* fuerte y estático, buenas capacidades tanto de programación de bajo nivel (*system programming*) como de alto nivel. Es -compatible de forma binaria con C (se puede enlazar código objeto C con -código objeto D). Con estas características, D_ logra llenar un vacío -importante que hay entre lo lenguajes de alto bajo nivel y los de alto -nivel [BKIP08]_. Si bien tiene herramientas de muy bajo nivel, que por lo -tanto son muy propensas a errores, da una infinidad de mecanismos para -evitar el uso de estas herramientas a menos que sea realmente necesario. -Además pone mucho énfasis en la programación confiable, para lo cual provee -muchos mecanismos para detectar errores en los programas de forma temprana. - -Si puede pensarse en C++ como un "mejor C", podría decirse que D_ es -un "mejor C++", ya que el objetivo del lenguaje es muy similar a C++, -pero implementa muchas características que jamás pudieron entrar en -el estándar de C++ y lo hace de una forma mucho más limpia, ya que -no debe lidiar con problemas de compatibilidad hacia atrás, y cuenta -con la experiencia del camino recorrido por C++, pudiendo extraer de -él los mejores conceptos pero evitando sus mayores problemas también. +compatible de forma binaria con C (se puede enlazar código objeto C con código +objeto D). Con estas características, D_ logra llenar un vacío importante que +hay entre lo lenguajes de alto bajo nivel y los de alto nivel [BKIP08]_. Si +bien tiene herramientas de muy bajo nivel, que por lo tanto son muy propensas +a errores, da una infinidad de mecanismos para evitar el uso de estas +herramientas a menos que sea realmente necesario. Además pone mucho énfasis +en la programación confiable, para lo cual provee muchos mecanismos para +detectar errores en los programas de forma temprana. + +Si puede pensarse en C++ como un "mejor C", podría decirse que D_ es un "mejor +C++", ya que el objetivo del lenguaje es muy similar a C++, pero implementa +muchas características que jamás pudieron entrar en el estándar de C++ y lo +hace de una forma mucho más limpia, ya que no debe lidiar con problemas de +compatibilidad hacia atrás, y cuenta con la experiencia del camino recorrido +por C++, pudiendo extraer de él los mejores conceptos pero evitando sus +mayores problemas también. Otra gran diferencia con C++ es la facilidad para ser analizado -gramaticalmente (*parsing*), ya fue especialmente diseñado para ser -sencillo y a diferencia de C y C++ su gramática es independiente del -contexto (*context-free grammar*). Esto permite que D pueda ser compilado -en pequeños pasos bien separados: +gramaticalmente (*parsing*), ya fue especialmente diseñado para ser sencillo +y a diferencia de C y C++ su gramática es independiente del contexto +(*context-free grammar*). Esto permite que D pueda ser compilado en pequeños +pasos bien separados: 1. Análisis léxico. 2. Análisis sintáctico. @@ -155,22 +149,21 @@ en pequeños pasos bien separados: 4. Optimizaciones. 5. Generación de código. -Esto favorece la creación de herramientas dada la facilidad de usar -solamente la cantidad de análisis necesario para cada herramienta (por -ejemplo un editor de textos puede tener hasta análisis sintáctico para -proveer resaltado o un entorno de desarrollo puede proveer herramientas de -re-factorización de código haciendo uso del análisis semántico). +Esto favorece la creación de herramientas dada la facilidad de usar solamente +la cantidad de análisis necesario para cada herramienta (por ejemplo un editor +de textos puede tener hasta análisis sintáctico para proveer resaltado o un +entorno de desarrollo puede proveer herramientas de re-factorización de código +haciendo uso del análisis semántico). - -Una de las características que nunca pudo entrar en el estándar de C++ -es la recolección de basura. D_ no comete el mismo error. +Una de las características que nunca pudo entrar en el estándar de C++ es la +recolección de basura. D_ no comete el mismo error. Características del lenguaje ---------------------------------------------------------------------------- -A continuación se enumeran las principales características de D_, -agrupadas por unidades funcional o paradigmas que soporta: +A continuación se enumeran las principales características de D_, agrupadas +por unidades funcional o paradigmas que soporta: @@ -182,25 +175,25 @@ Programación genérica y meta-programación La programación genérica se trata de la capacidad de poder desarrollar algoritmos y estructuras independientes de los tipos que manipulan (pero de forma segura o *type-safe*). Esto fue muy popularizado por C++ gracias a su -soporte de plantillas (*templates*) y luego otros lenguajes como Java_ -y `C#`_ lo siguieron. Sin embargo otros lenguajes proveen formas más -avanzadas de programación genérica, gracias a sistemas de tipos más -complejos (como Haskell_). - -La meta-programación se refiere en general a la capacidad de un lenguaje -para permitir generar código dentro del mismo programa de forma automática. -Esto permite evitar duplicación de código y fue también muy popularizado -por el soporte de *templates* de C++, aunque muchos otros lenguajes tienen -mejor soporte de meta-programación, en especial los lenguajes dinámicos -(como Python_). +soporte de plantillas (*templates*) y luego otros lenguajes como Java_ y `C#`_ +lo siguieron. Sin embargo otros lenguajes proveen formas más avanzadas de +programación genérica, gracias a sistemas de tipos más complejos (como +Haskell_). + +La meta-programación se refiere en general a la capacidad de un lenguaje para +permitir generar código dentro del mismo programa de forma automática. Esto +permite evitar duplicación de código y fue también muy popularizado por el +soporte de *templates* de C++, aunque muchos otros lenguajes tienen mejor +soporte de meta-programación, en especial los lenguajes dinámicos (como +Python_). D_ provee las siguientes herramientas para realizar programación genérica y meta-programación: ``if`` estático (``static if``): - puede verse como similar a la directiva del preprocesador de C/C++ - ``#if``, pero a diferencia de esto, en D_ el ``static if`` tiene acceso - a todos los símbolos del compilador (constantes, tipos, variables, etc). + puede verse como similar a la directiva del preprocesador de C/C++ ``#if``, + pero a diferencia de esto, en D_ el ``static if`` tiene acceso a todos los + símbolos del compilador (constantes, tipos, variables, etc). Ejemplo:: @@ -210,8 +203,8 @@ y meta-programación: Más información en http://www.digitalmars.com/d/1.0/version.html#staticif Inferencia de tipos básica implícita y explícita (mediante ``typeof``): - si no se especifica un tipo al declarar una variable, se infiere del - tipo de su inicializador. + si no se especifica un tipo al declarar una variable, se infiere del tipo + de su inicializador. Ejemplo:: @@ -222,8 +215,8 @@ Inferencia de tipos básica implícita y explícita (mediante ``typeof``): Más información en http://www.digitalmars.com/d/1.0/declaration.html#AutoDeclaration - Mediante el uso de ``typeof`` se puede solicitar el tipo de una - expresión arbitraria. + Mediante el uso de ``typeof`` se puede solicitar el tipo de una expresión + arbitraria. Ejemplo:: @@ -233,8 +226,8 @@ Inferencia de tipos básica implícita y explícita (mediante ``typeof``): Iteración sobre colecciones (``foreach``): cualquier tipo de colección (arreglos estáticos y dinámicos, arreglos - asociativos, clases, estructuras o delegados) puede ser iterada mediante - la sentencia ``foreach``. + asociativos, clases, estructuras o delegados) puede ser iterada mediante la + sentencia ``foreach``. Ejemplo:: @@ -245,10 +238,10 @@ Iteración sobre colecciones (``foreach``): *Templates*: clases y funciones pueden ser parametrizadas. Esto permite desarrollar - algoritmos genéricos sin importar el tipo de los datos de entrada, - siempre y cuando todos los tipos tengan una *interfaz* común. Esto - también es conocido como *polimorfismo en tiempo de compilación*, y es - la forma más básica de programación genérica. + algoritmos genéricos sin importar el tipo de los datos de entrada, siempre + y cuando todos los tipos tengan una *interfaz* común. Esto también es + conocido como *polimorfismo en tiempo de compilación*, y es la forma más + básica de programación genérica. Ejemplo:: @@ -256,12 +249,11 @@ Iteración sobre colecciones (``foreach``): auto i = sumar!(int)(5, 6); // i == 11 auto f = sumar!(float)(5, 6); // j == 11.0f - Además se pueden definir bloques de declaraciones parametrizados (esto - no es posible en C++), permitiendo instanciar dicho bloque con - parámetros particulares. Esto sirve como un mecanismo para la - reutilización de código, ya que puede incluirse un mismo bloque en - distintos lugares (por ejemplo clases). Un bloque parametrizado puede - verse como una especie de módulo. + Además se pueden definir bloques de declaraciones parametrizados (esto no + es posible en C++), permitiendo instanciar dicho bloque con parámetros + particulares. Esto sirve como un mecanismo para la reutilización de código, + ya que puede incluirse un mismo bloque en distintos lugares (por ejemplo + clases). Un bloque parametrizado puede verse como una especie de módulo. Ejemplo:: @@ -286,13 +278,13 @@ Instanciación implícita de funciones parametrizadas: auto f = sumar(5.0f, 6.0f); // f == 11.0f Especialización explícita y parcial de *templates*: - la especialización de *templates* consiste, al igual que en C++, en - proveer una implementación especializada para un tipo de dato (o valor) - de los parámetros. Especialización parcial se refiere a la capacidad - de especializar un parámetro a través de un subtipo. Por ejemplo, se - puede especializar un *template* para cualquier tipo de puntero, o para - cualquier tipo de arreglo dinámico, sin necesidad de especificar el tipo - al que apunta dicho puntero o el tipo almacenado por el arreglo. + la especialización de *templates* consiste, al igual que en C++, en proveer + una implementación especializada para un tipo de dato (o valor) de los + parámetros. Especialización parcial se refiere a la capacidad de + especializar un parámetro a través de un subtipo. Por ejemplo, se puede + especializar un *template* para cualquier tipo de puntero, o para cualquier + tipo de arreglo dinámico, sin necesidad de especificar el tipo al que + apunta dicho puntero o el tipo almacenado por el arreglo. Ejemplo de especialización:: @@ -311,8 +303,8 @@ Especialización explícita y parcial de *templates*: Tipos, valores (incluyendo *strings*) y *templates* como parámetros: esto es otro bloque de construcción importantísimo para la programación genérica en D, ya que combinando *templates* que toman *strings* como - parámetro en combinación con *string mixins* pueden hacerse toda clase - de meta-programas. + parámetro en combinación con *string mixins* pueden hacerse toda clase de + meta-programas. Ejemplo:: @@ -325,8 +317,8 @@ Tipos, valores (incluyendo *strings*) y *templates* como parámetros: string s = hash!("hola"); // calculado en tiempo de compilación Cantidad de parámetros variables para *templates*: - Esto permite implementar tuplas u otros algoritmos que inherentemente - deben tomar parámetros variables en tiempo de compilación. + Esto permite implementar tuplas u otros algoritmos que inherentemente deben + tomar parámetros variables en tiempo de compilación. Ejemplo:: @@ -340,12 +332,11 @@ Cantidad de parámetros variables para *templates*: *CTFE* (*compile-time function execution*): si una función cumple ciertas reglas básicas (como por ejemplo no tener - efectos colaterales) puede ser ejecutada en tiempo de compilación en vez - de tiempo de ejecución. Esto permite hacer algunos cálculos que no - cambian de ejecución en ejecución al momento de compilar, mejorando la - performance o permitiendo formas avanzadas de metaprogramación. Esta - característica se vuelve particularmente útil al combinarse con *string - mixins*. + efectos colaterales) puede ser ejecutada en tiempo de compilación en vez de + tiempo de ejecución. Esto permite hacer algunos cálculos que no cambian de + ejecución en ejecución al momento de compilar, mejorando la performance + o permitiendo formas avanzadas de metaprogramación. Esta característica se + vuelve particularmente útil al combinarse con *string mixins*. Ejemplo:: @@ -364,8 +355,8 @@ Cantidad de parámetros variables para *templates*: la palabra *mixin* tiene significados distintos en varios lenguajes de programación. En D_ *mixin* significa tomar una secuencia arbitraria de declaraciones e insertarla en el contexto (*scope*) actual. Esto puede - realizarse a nivel global, en clases, estructuras o funciones. Esto - sirve como un mecanismo para evitar duplicación de código que puede ser + realizarse a nivel global, en clases, estructuras o funciones. Esto sirve + como un mecanismo para evitar duplicación de código que puede ser introducida por la falta de herencia múltiple. Ejemplo:: @@ -386,10 +377,9 @@ Cantidad de parámetros variables para *templates*: *String mixin* se refiere a la capacidad de *incrustar* un *string* que contenga un fragmento de código en un programa como si este fragmento - hubiera sido escrito en el código fuente directamente por el - programador. Esto permite hacer manipulaciones arbitrariamente - complejas en combinación con funciones ejecutadas en tiempo de - compilación. + hubiera sido escrito en el código fuente directamente por el programador. + Esto permite hacer manipulaciones arbitrariamente complejas en combinación + con funciones ejecutadas en tiempo de compilación. Ejemplo:: @@ -404,10 +394,10 @@ Cantidad de parámetros variables para *templates*: Más información en http://www.digitalmars.com/d/1.0/mixin.html Expresiones ``is``: - las *expresiones ``is``* permiten la compilación condicional basada en - las características de un tipo. Esto se realiza en favor a una técnica - utilizada en C++ de realizar *pattern matching* sobre los parámetros de - las plantillas. + las *expresiones ``is``* permiten la compilación condicional basada en las + características de un tipo. Esto se realiza en favor a una técnica + utilizada en C++ de realizar *pattern matching* sobre los parámetros de las + plantillas. Ejemplo:: @@ -418,8 +408,7 @@ Expresiones ``is``: return T.init; } - Esto provee además una forma simple de reflexión en tiempo de - compilación. + Esto provee además una forma simple de reflexión en tiempo de compilación. Más información en http://www.digitalmars.com/d/1.0/expression.html#IsExpression @@ -431,24 +420,24 @@ Expresiones ``is``: Programación de bajo nivel (*system programming*) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Por programación de bajo nivel nos referimos a la capacidad de un lenguaje -de manipular el hardware directamente, o al menos la memoria. C es -probablemente el lenguaje de bajo nivel más popular, seguido por C++. +Por programación de bajo nivel nos referimos a la capacidad de un lenguaje de +manipular el hardware directamente, o al menos la memoria. C es probablemente +el lenguaje de bajo nivel más popular, seguido por C++. D_ presenta muchas características de bajo nivel: Compila a código de máquina nativo: - no es interpretado ni necesita una máquina virtual como otros lenguajes - de más alto nivel como Java_, `C#`_, Python_, etc. + no es interpretado ni necesita una máquina virtual como otros lenguajes de + más alto nivel como Java_, `C#`_, Python_, etc. Provee acceso a *assembly*: por lo tanto, acceso directo al *hardware* y la posibilidad de utilizar cualquier característica de éste que no esté disponible en el lenguaje. - Una ventaja sobre C y C++ es que el lenguaje *assembly* utilizado dentro - de D_ está especificado, por lo que se puede mantener la portabilidad - entre compiladores incluso cuando se utiliza *assembly* (mientras que no - se cambie de arquitectura, por supuesto). + Una ventaja sobre C y C++ es que el lenguaje *assembly* utilizado dentro de + D_ está especificado, por lo que se puede mantener la portabilidad entre + compiladores incluso cuando se utiliza *assembly* (mientras que no se + cambie de arquitectura, por supuesto). ``goto``: al igual que C y C++, D_ provee la flexibilidad del uso de ``goto``. @@ -467,20 +456,19 @@ Compatibilidad con C: printf("3 + 5 == %d\n", 3 + 5); // llama al printf de C Manejo de memoria explícito: - permite alocar estructuras en el *stack* o en el *heap*, haciendo uso de + permite asignar estructuras en el *stack* o en el *heap*, haciendo uso de los servicios del sistema operativo o la biblioteca estándar de C. Objetos y arreglos *livianos*: por objetos *livianos* se entiende no-polimórficos. Es decir, un - agrupamiento de variables análogo al ``struct`` de C, sin tabla virtual - ni otro tipo de *overhead*. Los arreglos *livianos* son arreglos - estáticos como en C, cuyo tamaño es fijo, también sin ningún tipo de - *overhead* como C. Además puede alocarse un arreglo dinámicamente usando - ``malloc()`` y utilizar el operador ``[]`` para accederlo. + agrupamiento de variables análogo al ``struct`` de C, sin tabla virtual ni + otro tipo de *overhead*. Los arreglos *livianos* son arreglos estáticos + como en C, cuyo tamaño es fijo, también sin ningún tipo de *overhead* como + C. Además puede asignarse un arreglo dinámicamente usando ``malloc()`` + y utilizar el operador ``[]`` para accederlo. - Esto también permite interoperar con C, ya que pueden definirse - ``structs`` y arreglos que pueden ser intercambiados con dicho lenguaje - sin problemas. + Esto también permite interoperar con C, ya que pueden definirse ``structs`` + y arreglos que pueden ser intercambiados con dicho lenguaje sin problemas. Ejemplo:: @@ -529,30 +517,29 @@ Control de alineación de miembros de una estructura: Programación de alto nivel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Programa de alto nivel se refiere a construcciones más avanzadas que un -loop. Expresiones semánticamente más ricas que permiten mayor expresividad -al programador o le permiten focalizarse de mejora manera en los algoritmos +Programa de alto nivel se refiere a construcciones más avanzadas que un loop. +Expresiones semánticamente más ricas que permiten mayor expresividad al +programador o le permiten focalizarse de mejora manera en los algoritmos independizándose del *hardware* o de como funciona una computadora. Es exactamente el opuesto a :ref:`d_low_level`. -En general estas características tiene como efecto secundario una mejora de -la productividad de los programadores. D_ adopta herramientas de muchos -lenguajes de alto nivel, como Java_ y Python_, por ejemplo: +En general estas características tiene como efecto secundario una mejora de la +productividad de los programadores. D_ adopta herramientas de muchos lenguajes +de alto nivel, como Java_ y Python_, por ejemplo: Manejo automático de memoria: al igual que C/C++ y prácticamente cualquier lenguaje imperativo maneja automáticamente el *stack*, pero a diferencia de la mayoría de los - lenguajes de bajo nivel, D_ permite manejar el *heap* de manera - automática también a través de un *recolección de basura*. + lenguajes de bajo nivel, D_ permite manejar el *heap* de manera automática + también a través de un *recolección de basura*. Sistema de paquetes y módulos (similar a Java_ o Python_): un módulo es una unidad que agrupa clases, funciones y cualquier otra construcción de lenguaje. Un paquete es una agrupación de módulos. D_ asocia un módulo a un archivo fuente (y un archivo objeto cuando éste es - compilado) y un paquete a un directorio. A diferencia de C/C++ no - necesita de un preprocesador para incluir declaraciones de otros - *módulos* (en C/C++ no existe el concepto de módulo, solo de unidades de - compilación). + compilado) y un paquete a un directorio. A diferencia de C/C++ no necesita + de un preprocesador para incluir declaraciones de otros *módulos* (en C/C++ + no existe el concepto de módulo, solo de unidades de compilación). Ejemplo: @@ -576,22 +563,22 @@ Sistema de paquetes y módulos (similar a Java_ o Python_): f(); // ejecuta b.f() Funciones y delegados: - las funciones pueden ser sobrecargadas (funciones con el mismo nombre - pero distinta cantidad o tipo de parámetros), pueden especificarse - argumentos de entrada, salida o entrada/salida, argumentos por omisión - o argumentos evaluados de forma perezosa (*lazy*). Además pueden tener - una cantidad de argumentos variables pero manteniendo información de - tipos (más seguro que C/C++). + las funciones pueden ser sobrecargadas (funciones con el mismo nombre pero + distinta cantidad o tipo de parámetros), pueden especificarse argumentos de + entrada, salida o entrada/salida, argumentos por omisión o argumentos + evaluados de forma perezosa (*lazy*). Además pueden tener una cantidad de + argumentos variables pero manteniendo información de tipos (más seguro que + C/C++). Los *delegados* son punteros a función con un contexto asociado. Este contexto puede ser un objeto (en cuyo caso la función es un método) o un *stack frame* (en cuyo caso la función es una función anidada). Además de esto los delegados son ciudadanos de primera clase - [#1stclasscity]_, disponiendo de forma literal (delegado anónimo), lo - que permite construcciones de alto nivel muy conveniente. Los argumentos - evaluados de forma perezosa no son más que un delegado que se ejecuta - solo cuando es necesario. + [#1stclasscity]_, disponiendo de forma literal (delegado anónimo), lo que + permite construcciones de alto nivel muy conveniente. Los argumentos + evaluados de forma perezosa no son más que un delegado que se ejecuta solo + cuando es necesario. .. [#1stclasscity] Por ciudadano de primera clase se entiende que se trata de un tipo soportado por completo por el lenguaje, disponiendo de @@ -625,12 +612,11 @@ Funciones y delegados: Arreglos *dinámicos* y arreglos asociativos: los arreglos *dinámicos* son arreglos de longitud variable manejados automáticamente por el lenguaje (análogos al ``std::vector`` de C++). - Soportan concatenación (a través del operador ``~``), rebanado - o *slicing* (a través del operador ``[x..y]``) y chequeo de límites - (*bound checking*). + Soportan concatenación (a través del operador ``~``), rebanado o *slicing* + (a través del operador ``[x..y]``) y chequeo de límites (*bound checking*). - Los arreglos asociativos (también conocidos como *hashes* - o diccionarios) también son provistos por el lenguaje. + Los arreglos asociativos (también conocidos como *hashes* o diccionarios) + también son provistos por el lenguaje. Ambos son ciudadanos de primera clase, disponiendo de forma literal. @@ -644,9 +630,9 @@ Arreglos *dinámicos* y arreglos asociativos: *Strings*: al igual que los delegados y arreglos dinámicos y asociativos, los - *strings* son ciudadanos de primera clase, teniendo forma literal - y siendo codificados en UTF-8/16/32. Son un caso particular de arreglo - dinámico y es posible utilizarlos en sentencias ``switch``/``case``. + *strings* son ciudadanos de primera clase, teniendo forma literal y siendo + codificados en UTF-8/16/32. Son un caso particular de arreglo dinámico y es + posible utilizarlos en sentencias ``switch``/``case``. Ejemplo:: @@ -661,11 +647,11 @@ Arreglos *dinámicos* y arreglos asociativos: ``typedef`` y ``alias``: el primero define un nuevo tipo basado en otro. A diferencia de C/C++ el - tipo original no puede ser implícitamente convertido al tipo nuevo - (excepto valores literales), pero la conversión es válida en el otro - sentido (similar a los ``enum`` en C++). Por el contrario, ``alias`` es - análogo al ``typedef`` de C/C++ y simplemente es una forma de referirse - al mismo tipo con un nombre distinto. + tipo original no puede ser implícitamente convertido al tipo nuevo (excepto + valores literales), pero la conversión es válida en el otro sentido + (similar a los ``enum`` en C++). Por el contrario, ``alias`` es análogo al + ``typedef`` de C/C++ y simplemente es una forma de referirse al mismo tipo + con un nombre distinto. Ejemplo:: @@ -681,8 +667,8 @@ Arreglos *dinámicos* y arreglos asociativos: Documentación embebida: D_ provee un sistema de documentación embebida, análogo a lo que provee - Java_ o Python_ en menor medida. Hay comentarios especiales del código - que pueden ser utilizados para documentarlo de forma tal que luego el + Java_ o Python_ en menor medida. Hay comentarios especiales del código que + pueden ser utilizados para documentarlo de forma tal que luego el compilador pueda extraer esa información para generar un documento. Más información en http://www.digitalmars.com/d/1.0/ddoc.html @@ -709,24 +695,22 @@ características más salientes se encuentran: Objetos *pesados*: objetos polimórficos como los de cualquier lenguaje con orientación real - a objetos. Estos objetos poseen una tabla virtual para *dispatch* - dinámico, todos los métodos son virtuales a menos que se indique lo - contrario y tienen semántica de referencia [#drefsem]_. Estos objetos - tienen un *overhead* comparados a los objetos *livianos* pero aseguran - una semántica segura para trabajar con orientación a objetos, evitando - problemas con los que se enfrenta C++ (como *slicing* [#dslicing]_) - debido a que permite semántica por valor [#dvalsem]_. + a objetos. Estos objetos poseen una tabla virtual para *dispatch* dinámico, + todos los métodos son virtuales a menos que se indique lo contrario + y tienen semántica de referencia [#drefsem]_. Estos objetos tienen un + *overhead* comparados a los objetos *livianos* pero aseguran una semántica + segura para trabajar con orientación a objetos, evitando problemas con los + que se enfrenta C++ (como *slicing* [#dslicing]_) debido a que permite + semántica por valor [#dvalsem]_. .. [#drefsem] Semántica de referencia significa que el tipo es tratado como si fuera un puntero. Nunca se hacen copias del objeto, siempre se pasa por referencia. - .. [#dslicing] Este problema se da en C++ cuando se pasa una clase derivada a una función que acepta una clase base por valor como parámetro. Al realizarse una copia de la clase con el constructor de copia de la clase base, se pierden (o *rebanan*) los atributos de la clase derivada, y la información de tipos en tiempo de ejecución (*RTTI*). - .. [#dvalsem] Semántica de valor significa que el tipo es tratado como si fuera un valor concreto. En general se pasa por valor y se hacen copias a menos que se utilice explícitamente un puntero. @@ -753,13 +737,13 @@ Objetos *pesados*: Interfaces: D_ no soporta herencia múltiple pero sí interfaces. Una interfaz es - básicamente una tabla virtual, una definición de métodos virtuales que - debe proveer una clase. Las interfaces no proveen una implementación de - dichos métodos, ni pueden tener atributos. Esto simplifica mucho el - lenguaje y no se pierde flexibilidad porque puede conseguirse el mismo - efecto de tener herencia múltiple a través de interfaces y *mixins* para - proveer una implementación o atributos en común a varias clases que - implementan la misma interfaz. + básicamente una tabla virtual, una definición de métodos virtuales que debe + proveer una clase. Las interfaces no proveen una implementación de dichos + métodos, ni pueden tener atributos. Esto simplifica mucho el lenguaje y no + se pierde flexibilidad porque puede conseguirse el mismo efecto de tener + herencia múltiple a través de interfaces y *mixins* para proveer una + implementación o atributos en común a varias clases que implementan la + misma interfaz. Sobrecarga de operadores: la sobrecarga de operadores permite que un objeto tenga una sintaxis @@ -782,11 +766,10 @@ Clases anidadas: } } - Esto tiene un pequeño *overhead* ya que la clase ``Anidada`` debe - guardar un puntero a la clase ``Exterior``. Si no se necesita este - comportamiento es posible evitar este *overhead* utilizando ``static``, - en cuyo caso solo puede acceder a atributos estáticos de la clase - ``Exterior``. + Esto tiene un pequeño *overhead* ya que la clase ``Anidada`` debe guardar + un puntero a la clase ``Exterior``. Si no se necesita este comportamiento + es posible evitar este *overhead* utilizando ``static``, en cuyo caso solo + puede acceder a atributos estáticos de la clase ``Exterior``. Ejemplo:: @@ -847,8 +830,8 @@ Propiedades (*properties*): ``alignof`` alineación de una estructura o tipo. - Estos son solo los *properties* predefinidos para todos los tipos, pero - hay una cantidad considerable de *properties* extra para cada tipo. + Estos son solo los *properties* predefinidos para todos los tipos, pero hay + una cantidad considerable de *properties* extra para cada tipo. Más información sobre *properties* de clases en http://www.digitalmars.com/d/1.0/property.html#classproperties y sobre @@ -860,27 +843,26 @@ Propiedades (*properties*): Programación confiable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Programación confiable se refiere a las capacidades o facilidades que -provee el lenguaje para evitar fallas de manera temprano (o la capacidad de -evitar que ciertas fallas puedan existir directamente). D_ presta -particular atención a esto y provee las siguientes herramientas: +Programación confiable se refiere a las capacidades o facilidades que provee +el lenguaje para evitar fallas de manera temprano (o la capacidad de evitar +que ciertas fallas puedan existir directamente). D_ presta particular atención +a esto y provee las siguientes herramientas: Excepciones: - D_ soporta excepciones de manera similar a Java_: provee ``try``, - ``catch`` y ``finally``. Esto permite que los errores difícilmente pasen + D_ soporta excepciones de manera similar a Java_: provee ``try``, ``catch`` + y ``finally``. Esto permite que los errores difícilmente pasen silenciosamente sin ser detectados. ``assert``: - es una condición que debe cumplirse siempre en un programa, como un - chequeo de integridad. Esto es muy utilizado en C/C++, donde - ``assert()`` es una *macro* que solo se compila cuando la *macro* - ``NDEBUG`` no está definida. Esto permite eliminar los chequeos de - integridad del programa, que pueden ser costosos, para versiones que se - suponen estables. + es una condición que debe cumplirse siempre en un programa, como un chequeo + de integridad. Esto es muy utilizado en C/C++, donde ``assert()`` es una + *macro* que solo se compila cuando la *macro* ``NDEBUG`` no está definida. + Esto permite eliminar los chequeos de integridad del programa, que pueden + ser costosos, para versiones que se suponen estables. D_ lleva este concepto más allá y hace al ``assert`` parte del lenguaje. - Si una verificación no se cumple, lanza una excepción. El ``assert`` no - es compilado cuando se utiliza una opción del compilador. + Si una verificación no se cumple, lanza una excepción. El ``assert`` no es + compilado cuando se utiliza una opción del compilador. Ejemplo:: @@ -888,14 +870,14 @@ Excepciones: assert (f.ok()); Diseño por contrato: - el diseño por contrato es un concepto introducido por el lenguaje - Eiffel_ a mediados/finales de los '80. Se trata de incorporar en el - lenguaje las herramientas para poder aplicar verificaciones formales - a las interfaces de los programas. + el diseño por contrato es un concepto introducido por el lenguaje Eiffel_ + a mediados/finales de los '80. Se trata de incorporar en el lenguaje las + herramientas para poder aplicar verificaciones formales a las interfaces de + los programas. D_ implementa las siguientes formas de diseño por contrato (todas se - ejecutan siempre y cuando no se compile en modo *release*, de manera de - no sacrificar *performance* cuando es necesario): + ejecutan siempre y cuando no se compile en modo *release*, de manera de no + sacrificar *performance* cuando es necesario): Pre y post condiciones: Ejemplo:: @@ -918,11 +900,11 @@ Diseño por contrato: } Invariantes de representación: - La invariante de representación es un método de una clase - o estructura que es verificada cuando se completa su construcción, - antes de la destrucción, antes y después de ejecutar cualquier - función miembro pública y cuando se lo requiere de forma explícita - utilizando ``assert``. + La invariante de representación es un método de una clase o estructura + que es verificada cuando se completa su construcción, antes de la + destrucción, antes y después de ejecutar cualquier función miembro + pública y cuando se lo requiere de forma explícita utilizando + ``assert``. Ejemplo:: @@ -955,17 +937,17 @@ Orden de construcción estática: a diferencia de C++, D_ garantiza el orden de inicialización de los módulos. Si bien en C++ no hay módulos si no unidades de compilación, es posible que se ejecute código antes del ``main()`` en C++, si hay, por - ejemplo, instancias globales con un constructor definido. C++ no - garantiza un orden de inicialización, lo que trae muchos problemas. En - D_ se define el orden de inicialización y es el mismo orden en que el - usuario importa los módulos. + ejemplo, instancias globales con un constructor definido. C++ no garantiza + un orden de inicialización, lo que trae muchos problemas. En D_ se define + el orden de inicialización y es el mismo orden en que el usuario importa + los módulos. Inicialización garantizada: todas las variables son inicializadas por el lenguaje (a menos que el usuario pida explícitamente que no lo sean). Siempre que sea posible se - elijen valores de inicialización que permitan saber al programador que - la variable no fue inicializada explícitamente, de manera de poder - detectar errores de manera temprana. + elijen valores de inicialización que permitan saber al programador que la + variable no fue inicializada explícitamente, de manera de poder detectar + errores de manera temprana. Ejemplo:: @@ -976,16 +958,16 @@ Inicialización garantizada: long l = void; // NO inicializado (explícitamente) *RAII* (*Resource Adquisition Is Initialization*): - es una técnica muy utilizada en C++ que consiste en reservar recursos - por medio de la construcción de un objeto y liberarlos cuando se libera - éste. Al llamarse al destructor de manera automática cuando se sale del - *scope*, se asegura que el recurso será liberado también. + es una técnica muy utilizada en C++ que consiste en reservar recursos por + medio de la construcción de un objeto y liberarlos cuando se libera éste. + Al llamarse al destructor de manera automática cuando se sale del *scope*, + se asegura que el recurso será liberado también. Esta técnica es la base para desarrollar código seguro en cuanto a excepciones (*exception-safe*) [SUTT99]_. - En D_ no es tan común utilizar *RAII* dada la existencia del recolector - de basura (en la mayoría de los casos el recurso a administrar es + En D_ no es tan común utilizar *RAII* dada la existencia del recolector de + basura (en la mayoría de los casos el recurso a administrar es sencillamente memoria). Sin embargo en los casos en donde es necesario, puede utilizarse *RAII* mediante la utilización de la palabra reservada ``scope``, que limita la vida de un objeto un bloque de código. @@ -1002,10 +984,9 @@ Inicialización garantizada: } // en este punto se llama al destructor de archivo Guardias de bloque (*scope guards*): - además de poder limitar la vida de una instancia a un *scope*, es - posible especificar un bloque de código arbitrario a ejecutar al - abandonar un *scope*, ya sea cuando se sale del *scope* normalmente - o por una falla. + además de poder limitar la vida de una instancia a un *scope*, es posible + especificar un bloque de código arbitrario a ejecutar al abandonar un + *scope*, ya sea cuando se sale del *scope* normalmente o por una falla. Ejemplo:: @@ -1025,18 +1006,18 @@ Guardias de bloque (*scope guards*): return 0; // ejecuta lock.unlock() y trans.commit() } - Esta es una nueva forma de poder escribir código *exception-safe*, - aunque el programador debe tener un poco más de cuidado de especificar - las acciones a ejecutar al finalizar el *scope*. + Esta es una nueva forma de poder escribir código *exception-safe*, aunque + el programador debe tener un poco más de cuidado de especificar las + acciones a ejecutar al finalizar el *scope*. Primitivas de sincronización de hilos: la programación multi-hilo está directamente soportada por el lenguaje, - y se provee una primitiva de sincronización al igual que Java_. La - palabra reservada ``synchronized`` puede aparecer como modificador de - métodos (en cuyo caso se utiliza un *lock* por clase para sincronizar) - o como una sentencia, en cuyo caso se crea un *lock* global por cada - bloque ``synchronized`` a menos que se especifique sobre qué objeto - realizar la sincronización. Por ejemplo:: + y se provee una primitiva de sincronización al igual que Java_. La palabra + reservada ``synchronized`` puede aparecer como modificador de métodos (en + cuyo caso se utiliza un *lock* por clase para sincronizar) o como una + sentencia, en cuyo caso se crea un *lock* global por cada bloque + ``synchronized`` a menos que se especifique sobre qué objeto realizar la + sincronización. Por ejemplo:: class Foo { synchronized void bar() { /* cuerpo */ } @@ -1059,9 +1040,9 @@ y LDC_. DMD_ es el compilador de referencia, escrito por `Walter Bright`_. El *front-end* [#frontend]_ de este compilador ha sido liberado bajo licencia -Artistic_/GPL_ y es utilizado por los otros dos compiladores, por lo -tanto en realidad hay solo un compilador disponible con 3 *back-ends* -[#backend]_ diferentes. +Artistic_/GPL_ y es utilizado por los otros dos compiladores, por lo tanto en +realidad hay solo un compilador disponible con 3 *back-ends* [#backend]_ +diferentes. .. [#frontend] *Front-end* es la parte del compilador encargada de hacer el análisis léxico, sintáctico y semántico del código fuente, generando una @@ -1072,38 +1053,37 @@ tanto en realidad hay solo un compilador disponible con 3 *back-ends* la representación intermedia generada por el *front-end* a código de máquina. -Con `DMD 1.041`__ se publicó el código fuente completo del compilador, -pero con una licencia muy restrictiva para uso personal, por lo que el -único efecto logrado por esto es que la gente pueda mandar parches -o correcciones del compilador pero no lo convierte en `Software Libre`_, -siendo el único de los 3 compiladores que no tiene esta característica. +Con `DMD 1.041`__ se publicó el código fuente completo del compilador, pero +con una licencia muy restrictiva para uso personal, por lo que el único efecto +logrado por esto es que la gente pueda mandar parches o correcciones del +compilador pero no lo convierte en `Software Libre`_, siendo el único de los +3 compiladores que no tiene esta característica. __ http://www.digitalmars.com/d/1.0/changelog.html#new1_041 El compilador GDC_ es el *front-end* de DMD_ utilizando al compilador GCC_ como *back-end*. Fue un muy buen compilador pero en la actualidad está -abandonado. No hay un *release* desde agosto de 2007 y no hay -actualizaciones serias del código desde mediados de 2008, por lo que no -parece haber muchas probabilidades de que se siga manteniendo. - -LDC_ es lo opuesto; un compilador joven, nacido a mediados de 2007 (aunque -vio la luz un año después aproximadamente), su primer *release* fue -a principios de 2009 y tuvo un crecimiento excepcional. En la actualidad -inclusive pasa más pruebas de estrés que el compilador de referencia DMD_. -Como *back-end* utiliza LLVM_, otro proyecto joven y con una tasa de -crecimiento muy alta. - -Además de estos compiladores hay varios otros experimentales, pero ninguno -de ellos de calidad suficiente todavía. Por ejemplo hay un compilador -experimental que emite *CIL* (*Common Intermediate Language*), el -*bytecode* de `.NET`_, llamado DNet_. También hay un *fron-end* escrito en -D_, llamado Dil_ +abandonado. No hay un *release* desde agosto de 2007 y no hay actualizaciones +serias del código desde mediados de 2008, por lo que no parece haber muchas +probabilidades de que se siga manteniendo. + +LDC_ es lo opuesto; un compilador joven, nacido a mediados de 2007 (aunque vio +la luz un año después aproximadamente), su primer *release* fue a principios +de 2009 y tuvo un crecimiento excepcional. En la actualidad inclusive pasa más +pruebas de estrés que el compilador de referencia DMD_. Como *back-end* +utiliza LLVM_, otro proyecto joven y con una tasa de crecimiento muy alta. + +Además de estos compiladores hay varios otros experimentales, pero ninguno de +ellos de calidad suficiente todavía. Por ejemplo hay un compilador +experimental que emite *CIL* (*Common Intermediate Language*), el *bytecode* +de `.NET`_, llamado DNet_. También hay un *fron-end* escrito en D_, llamado +Dil_ Originalmente, dado que GDC_ estaba siendo mantenido y que LDC_ no existía, -este trabajo iba a ser realizado utilizando GDC_ como compilador, dado que -al ser `Software Libre`_ podía ser modificado de ser necesario. Finalmente, -gracias a la excepcional tasa de crecimiento de LDC_ y al abandono de GDC_ -se terminó desarrollando el trabajo utilizando LDC_. +este trabajo iba a ser realizado utilizando GDC_ como compilador, dado que al +ser `Software Libre`_ podía ser modificado de ser necesario. Finalmente, +gracias a la excepcional tasa de crecimiento de LDC_ y al abandono de GDC_ se +terminó desarrollando el trabajo utilizando LDC_.