.. Introducción y breve reseña del lenguaje de programación D. También
se presentan las necesidades particulares de D con respecto al
recolector de basura y su estado actual.
- ESTADO: TERMINADO
+ ESTADO: TERMINADO, CORREGIDO (A)
+.. highlight:: d
+
.. _d_lang:
El lenguaje de programación D
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.
+el desarrollo del lenguaje en la `versión 2.0`__, que pasó a ser considerada
+estable aproximadamente en junio de 2010 con el lanzamiento del libro "The
+D Programming Language" [ALX10]_, pero aún es un trabajo en progreso.
__ `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 compiladores de C++ que
+compilaba a código nativo, y está fuertemente influenciado por éste. Sin
+embargo toma muchos conceptos de otros lenguajes de más alto nivel, como Java_
+o incluso lenguajes dinámicos como Perl_, Python_ y Ruby_.
El origen del lenguaje está plasmado en su sitio web, en donde se cita:
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).
+estabilidad y completitud. 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
+ lenguajes funcionales en general, abriendo 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*), agregando
+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.
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
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
+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`_.
+de Tango_ (Kris Bell, Sean Kelly, Lars Ivar Igesund y Michael Parker) publican
+el libro llamado `Learn to Tango with D`_ [BKIP08]_.
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).
+lenguaje pero por otro un gran retroceso, porque todavía al día de hoy `D
+1.0`_ tiene dos bibliotecas base, una estándar pero de peor calidad, menos
+mantenida y usada; 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 considerable 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 dos 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`_. Sin embargo
+Tango_ no fue adaptada a `D 2.0`_ todavía, y no hay muchas perspectivas de que
+sea portada en algún momento, por un lado porque en general la comunidad sigue
+fragmentada entre muchos usuarios de `D 1.0`_ que no están contentos con los
+cambios introducidos en `D 2.0`_, en su mayoría usuarios de Tango_, y que no
+planean migrar a esa versión; y por otro porque el desarrollo de Phobos_ 2.0
+se ha abierto mucho y tiene muchos colaboradores, por lo tanto la mayor parte
+de la gente que utiliza `D 2.0`_ está contenta con el estado de Phobos_ 2.0.
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.
+programación de bajo nivel (*system programming*) como de alto nivel; además
+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
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.
+mayores problemas.
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
+sintácticamente (*parsing*), ya que 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:
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
+la cantidad de análisis necesario para cada una (por ejemplo un editor de
+textos puede tener hasta análisis sintáctico para proveer resaltado o un
+entorno de desarrollo puede proveer herramientas para re-factorizar el 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
----------------------------------------------------------------------------
A continuación se enumeran las principales características de D_, agrupadas
-por unidades funcional o paradigmas que soporta:
+por unidades funcionales o paradigmas que soporta:
D_ provee las siguientes herramientas para realizar programación genérica
y meta-programación:
-``if`` estático (``static if``):
+``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).
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``):
+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.
+ de su valor de inicialización.
Ejemplo::
Más información en http://www.digitalmars.com/d/1.0/declaration.html#typeof
-Iteración sobre colecciones (``foreach``):
+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``.
foreach (i; a)
total += i;
-*Templates*:
- clases y funciones pueden ser parametrizadas. Esto permite desarrollar
+*Templates*
+ clases y funciones pueden ser generalizadas. 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
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
+ Además se pueden definir bloques de declaraciones generalizadas (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.
+ clases). Un bloque generalizado puede verse como una especie de módulo.
Ejemplo::
bloque!(int, float).x = 5;
float f = bloque!(int, float).foo(7);
- La utilidad más prominente de los bloques parametrizados se da al
+ La utilidad más prominente de los bloques generalizados se da al
acompañarse de *mixins*.
-Instanciación implícita de funciones parametrizadas:
+Instanciación implícita de funciones generalizadas
el lenguaje es capaz de deducir los parámetros siempre que no hayan
- ambigüedades
+ ambigüedades.
Ejemplo::
auto i = sumar(5, 6); // i == 11
auto f = sumar(5.0f, 6.0f); // f == 11.0f
-Especialización explícita y parcial de *templates*:
+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
float v = 5.0f, w = 6.0f;
auto f = sumar(&v, &w); // f == 11.0f
-Tipos, valores (incluyendo *strings*) y *templates* como parámetros:
+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
template hash(string s, uint so_far=0) {
static if (s.length == 0)
- const hash = sofar;
+ const hash = so_far;
else
- const hash = hash!(s[1 .. length], sofar * 11 + s[0]);
+ const hash = hash!(s[1 .. length], so_far * 11 + s[0]);
}
string s = hash!("hola"); // calculado en tiempo de compilación
-Cantidad de parámetros variables para *templates*:
+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.
+ tomar una cantidad variable de parámetros en tiempo de compilación.
Ejemplo::
}
double d = sumar(1, 2.0, 3.0f, 4l); // d == 10.0
-*CTFE* (*compile-time function execution*):
+*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
+ ejecución en ejecución al momento de compilar, mejorando el rendimiento
+ o permitiendo formas avanzadas de meta-programación. Esta característica se
vuelve particularmente útil al combinarse con *string mixins*.
Ejemplo::
Esta característica es vital para evitar la duplicación de código.
-*Mixins*, incluyendo *string mixins*:
+*Mixins*, incluyendo *string mixins*
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
Más información en http://www.digitalmars.com/d/1.0/mixin.html
-Expresiones ``is``:
+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.
+ características de un tipo.
Ejemplo::
D_ presenta muchas características de bajo nivel:
-Compila a código de máquina nativo:
+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.
-Provee acceso a *assembly*:
+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.
compiladores incluso cuando se utiliza *assembly* (mientras que no se
cambie de arquitectura, por supuesto).
-``goto``:
+``goto``
al igual que C y C++, D_ provee la flexibilidad del uso de ``goto``.
-Compatibilidad con C:
+Compatibilidad con C
soporta todos los tipos de C y es ABI [#abi]_ compatible con éste. Esto
permite enlazar archivos objeto estándar de C y D_ en un mismo programa.
Además permite interoperar con C a través de ``extern (C)``.
extern (C) printf(const char* format, ...);
printf("3 + 5 == %d\n", 3 + 5); // llama al printf de C
-Manejo de memoria explícito:
+Manejo de memoria explícito
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*:
+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
timeval tv;
gettimeofday(&tv, null);
-Rendimiento:
+Rendimiento
la :ref:`d_generic` permite realizar muchas optimizaciones ya que se
- resuelve en tiempo de compilación y por lo tanto aumentando la
- *performance* en la ejecución.
+ resuelve en tiempo de compilación y por lo tanto aumenta el rendimiento en
+ la ejecución.
-Número de punto flotante de 80 bits:
+Número de punto flotante de 80 bits
El tipo ``real`` de D_ tiene precisión de 80 bits si la plataforma lo
soporta (por ejemplo en i386).
-Control de alineación de miembros de una estructura:
+Control de alineación de miembros de una estructura
Mediante ``align`` se puede especificar la alineación a tener en 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
-independizándose del *hardware* o de como funciona una computadora. Es
-exactamente el opuesto a :ref:`d_low_level`.
+Programación de alto nivel se refiere a construcciones más avanzadas que una
+sentencia para iterar; expresiones con una semántica más ricas que proveen de
+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
+En general estas características tienen 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:
+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*.
+ también a través de un *recolector de basura*.
-Sistema de paquetes y módulos (similar a Java_ o Python_):
+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
b.f();
f(); // ejecuta b.f()
-Funciones y delegados:
+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
bool buscar(T[] arreglo, T item, bool delegate(T x, T y) igual) {
foreach (t, arreglo)
- if (igual(t, elemento))
+ if (igual(t, item))
return true;
return false;
}
}
);
-Arreglos *dinámicos* y arreglos asociativos:
+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*
int[string] agenda;
agenda["Pepe"] = 5555_1234;
-*Strings*:
+*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
s = "";
}
-``typedef`` y ``alias``:
+``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
un_alias a = t;
foo(a);
-Documentación embebida:
- D_ provee un sistema de documentación embebida, análogo a lo que provee
+Documentación embebida
+ D_ provee un sistema de documentación embebida, análogo a lo que proveen
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
-Números complejos:
+Números complejos
D_ soporta números complejos como ciudadanos de primera clase. Soporta
forma literal de números imaginarios y complejos.
herramientas para soportar este paradigma de forma confiable. Entre las
características más salientes se encuentran:
-Objetos *pesados*:
+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,
+ a objetos. Estos objetos poseen una tabla virtual para despacho 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
Más información en http://www.digitalmars.com/d/1.0/function.html
-Interfaces:
+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
implementación o atributos en común a varias clases que implementan la
misma interfaz.
-Sobrecarga de operadores:
+Sobrecarga de operadores
la sobrecarga de operadores permite que un objeto tenga una sintaxis
similar a un tipo de dato nativo. Esto es muy importante además para la
programación genérica.
-Clases anidadas:
+Clases anidadas
al igual que C (con respecto a ``struct``) y C++, pueden anidarse clases
dentro de clases. D_ sin embargo provee la posibilidad de acceder
a atributos de la instancia exterior desde la anidada.
}
-Propiedades (*properties*):
+Propiedades (*properties*)
en D_ se refiere a funciones miembro que pueden ser tratadas
sintácticamente como campos de esa clase/estructura.
Además tipos nativos, clases, estructuras y expresiones tienen
*properties* predefinidos, por ejemplo:
- ``sizeof``:
+ ``sizeof``
tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4).
- ``init``:
+ ``init``
valor de inicialización por omisión (ejemplo: ``float.init`` -> *NaN*
[#dnan]_).
.. [#dnan] Del inglés *Not A Number*, es un valor especial que indica que
estamos ante un valor inválido.
- ``stringof``:
- representación textual del tipo (ejemplo: ``(1+2).stringof`` -> ``"1
- + 2"``).
+ ``stringof``
+ representación textual del símbolo o expresión (ejemplo:
+ ``(1+2).stringof`` -> ``"1 + 2"``).
- ``mangleof``:
+ ``mangleof``
representación textual del tipo *mutilado* [#dmangle]_.
.. [#dmangle] *Name mangling* es el nombre dado comunmente a una técnica
+.. _d_dbc:
+
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
+el lenguaje para evitar fallas de manera temprana (o la capacidad de evitar
que ciertas fallas puedan existir directamente). D_ presta particular atención
a esto y provee las siguientes herramientas:
-Excepciones:
+Excepciones
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``:
+``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.
File f = open("archivo");
assert (f.ok());
-Diseño por contrato:
+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
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):
+ sacrificar rendimiento cuando es necesario):
- Pre y post condiciones:
+ Pre y post condiciones
Ejemplo::
double raiz_cuadrada(double x)
// implementación
}
- Invariantes de representación:
+ 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
Más información en http://www.digitalmars.com/d/1.0/dbc.html
-Pruebas unitarias:
+Pruebas unitarias
es posible incluir pequeñas pruebas unitarias en el lenguaje. Éstas son
ejecutadas (cuando no se compila en modo *release*) al comenzar el
programa, antes de que la función ``main()``.
assert (fecha);
}
-Orden de construcción estática:
+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
el orden de inicialización y es el mismo orden en que el usuario importa
los módulos.
-Inicialización garantizada:
+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
Ejemplo::
- double d; // inicializado a NaN
- int x; // inicializado a 0
- Fecha f; // inicializado a null
- byte[5] a; // inicializados todos los valores a 0
+ double d; // inicializado a NaN
+ int x; // inicializado a 0
+ Fecha f; // inicializado a null
+ byte[5] a; // inicializados todos los valores a 0
long l = void; // NO inicializado (explícitamente)
-*RAII* (*Resource Adquisition Is Initialization*):
+*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*,
// uso de archivo
} // en este punto se llama al destructor de archivo
-Guardias de bloque (*scope guards*):
+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.
int f(Lock lock) {
lock.lock();
scope (exit)
- lock.unlock(); // ejecutado siempre que salga de f()
+ lock.unlock(); // ejecutado siempre que salga de f()
auto trans = new Transaccion;
scope (success)
- trans.commit(); // ejecutado si sale con "return"
+ trans.commit(); // ejecutado si sale con "return"
scope (failure)
- trans.rollback(); // ejecutado si sale por una excepción
+ trans.rollback(); // ejecutado si sale por una excepción
if (condicion)
- throw Exception("error"); // ejecuta lock.unlock() y trans.rollback()
+ throw Exception("error"); // lock.unlock() y trans.rollback()
else if (otra_condicion)
- return 5; // ejecuta lock.unlock() y trans.commit()
- return 0; // ejecuta lock.unlock() y trans.commit()
+ return 5; // lock.unlock() y trans.commit()
+ return 0; // 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*.
-Primitivas de sincronización de hilos:
+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
__ 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.
+como *back-end*. Fue un muy buen compilador pero estuvo abandonado por casi
+tres años. A mediados de este año recibió un nuevo impulso y de a poco se está
+poniendo al día con los *front-ends* actuales de DMD_ 1.0 y 2.0, aunque la
+versión 2.0 viene bastante más rezagada y todavía no es una alternativa viable
+a DMD_.
+
+LDC_ sufrió una suerte similar, es un compilador joven que utiliza como
+*back-end* a LLVM_ (una infraestructura modera para construir compiladores),
+nacido a mediados de 2007 como un proyecto personal y privado de Tomas
+Lindquist Olsen, que estuvo trabajando de forma privada en el proyecto hasta
+mediados de 2008, momento en que decide publicar el código mediante una
+licencia libre. Para ese entonces el compilador era todavía inestable
+y faltaban implementar varias cosas, pero el estado era lo suficientemente
+bueno como para captar varios colaboradores muy capaces, como `Christian
+Kamm`_ y Frits Van Bommel que rápidamente se convirtieron en parte fundamental
+del proyecto. El primer *release* (0.9) de una versión relativamente completa
+y estable fue a principios de 2009 que fue seguido por la versión 0.9.1 que
+como puntos más salientes agregó soporte para x86-64 y assembly embebido. El
+compilador tuvo un crecimiento excepcional pero estuvo muy inactivo por algún
+tiempo y, si bien sigue siendo mantenido, en general los nuevos *front-end* de
+DMD_ llevan tiempo de integrar y no está al día con el *back-end* de LLVM_
+(por ejemplo desde que se actualizó para utilizar LLVM_ 2.7 que perdió la
+capacidad de generar símbolos de depuración).
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_
+de `.NET`_, llamado DNet_. También hay un *front-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_.
-
+ser `Software Libre`_ podía ser modificado de ser necesario. Pero finalmente,
+dada la poca confiabilidad que presenta la continuidad del desarrollo de tanto
+GDC_ como LDC_, y que el código de DMD_ está disponible en su totalidad
+(aunque no sea `Software Libre`_ por completo), se optó por utilizar este
+último, dado que es la implementación de referencia que fue más constantemente
+mantenida y desarrollada.
.. include:: links.rst
-.. vim: set ts=3 sts=3 sw=3 et tw=78 :
+.. vim: set ts=3 sts=3 sw=3 et tw=78 spelllang=es :