__ `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,
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.
+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`_.
+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 dos 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 considerable 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 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. Si bien todavía
-Tango_ no fue adaptada a D 2.0, se espera que cuando esto pase compartan la
+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.
+ y Phobos_ 2.0 puedan coexistir sin problemas.
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
-sintácticamente (*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:
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::
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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:
Por último, siendo que el recolector de basura es parte del programa de forma
indirecta, es común ver en la literatura que se diferencia entre dos partes
-del programa, el recolector de basura y el programa en sí. Dado que para el
-recolector de basura, lo único que interesa conocer del programa en sí son los
-cambios al grafo de conectividad de las celdas, normalmente se lo llama
-*mutator*.
+del programa, el recolector de basura y el programa en sí. A la primera se la
+suele denominar simplemente *recolector* y a la segunda *mutator*, dado que es
+la única que modifica (o *muta*) el grafo de conectividad.
Al proceso de visitar los vértices *conectados* desde el *root set* se lo
denomina *marcado*, *fase de marcado* o *mark phase* en inglés, debido a que
-es necesario marcar los vértices para evitar visitar 2 veces el mismo nodo en
+es necesario marcar los vértices para evitar visitar dos veces el mismo nodo en
casos de que el grafo contenga ciclos [#gccycle]_. De forma similar a la
búsqueda, que puede realizarse *primero a lo ancho* (*breadth-first*)
o *primero a lo alto* (*depth-first*) del grafo, el marcado de un grafo
Si bien este algoritmo no es recursivo, tiene un requerimiento de espacio
:math:`O(\lvert Live \thickspace set \rvert)`. Un ejemplo donde se aprecia
-esto a simple vista es cuando el *live set* resulta una lista simplemente
-enlazada, en cuyo caso el :math:`gray_set` deberá almacenar todos los nodos
-del *live set*.
+esto a simple vista es cuando el *Live set* resulta una lista simplemente
+enlazada, en cuyo caso el *gray_set* deberá almacenar todos los nodos del
+*Live set*.
referencias <gc_rc>`. Para otros recolectores puede significar que el
usuario asegura que no hay más referencias a esta celda, es decir, análogo
a eliminar el conjunto de aristas :math:`\big\lbrace (v, w) \in A , v \in
- Live \thickspace set , w \in Live \thickspace set \big/ w = cell`.
+ Live \thickspace set , w \in Live \thickspace set \big/ w = cell
+ \big\rbrace`.
:math:`collect()`
indica al recolector que debe hacer un análisis del grafo de conectividad
Algoritmos clásicos
----------------------------------------------------------------------------
-En la literatura se encuentran normalmente referencias a 3 algoritmos
+En la literatura se encuentran normalmente referencias a tres algoritmos
clásicos, que son utilizados generalmente como bloques básicos para construir
recolectores más complejos. Se presentan las versiones históricas más simples
a fin de facilitar la comprensión conceptual.
inicial* es el mismo que el *vértice final*.
Cuando esto sucede, las celdas que participan del ciclo tienen siempre su
-contador mayor que 0, sin embargo puede no haber ningún elemento del *root
-set* que apunte a una celda dentro del ciclo, por lo tanto el ciclo es
-*basura* (al igual que cualquier otra celda para la cual hayan referencias
-desde el ciclo pero que no tenga otras referencias externas) y sin embargo los
+contador mayor que 0, sin embargo puede suceder que ningún elemento del *root
+set* apunte a una celda dentro del ciclo, por lo tanto el ciclo es *basura*
+(al igual que cualquier otra celda para la cual hayan referencias desde el
+ciclo pero que no tenga otras referencias externas) y sin embargo los
contadores no son 0. Los ciclos, por lo tanto, violan la invariante del conteo
de referencia.
Hay formas de solucionar esto, pero siempre recaen en un esquema que va por
fuera del conteo de referencias puro. En general los métodos para solucionar
esto son variados y van desde realizar un marcado del sub-grafo para detectar
-nodos hasta tener otro recolector completo de *emergencia*, pasando por tratar
-los ciclos como un todo contar las referencias al ciclo completo en vez de
-a cada celda en particular.
+ciclos y liberarlos hasta tener otro recolector completo de *emergencia*;
+pasando por tratar los ciclos como un todo para contar las referencias al
+ciclo completo en vez de a cada celda en particular.
Incluso con este problema, el conteo de referencia sin ningún tipo de solución
en cuanto a la detección y recolección de ciclos fue utilizado en muchos
Ejemplo de conteo de referencias: actualización de una referencia (parte 1).
- Cambio en la referencia ``h2.l`` :math:`\to` ``h2`` a ``h2.l`` :math:`\to`
+ Cambio en la referencia ``h3.l`` :math:`\to` ``h2`` a ``h3.l`` :math:`\to`
``h5`` (parte 1).
.. subfig::
.. subfig::
- Luego se procede a visitar las hijas de ``h3``, comenzando por ``h2``.
+ Luego se procede a visitar la antigua referencia de ``h3.l`` (``h2``).
.. digraph:: g4_2
Ejemplo de conteo de referencias: actualización de una referencia (parte 2).
- Cambio en la referencia ``h2.l`` :math:`\to` ``h2`` a ``h2.l`` :math:`\to`
+ Cambio en la referencia ``h3.l`` :math:`\to` ``h2`` a ``h3.l`` :math:`\to`
``h5`` (parte 2).
.. subfig::