]> git.llucax.com Git - z.facultad/75.00/informe.git/blobdiff - source/d.rst
Agregar descripción del GC actual de D
[z.facultad/75.00/informe.git] / source / d.rst
index f916af0f20516a49228e9c479f9734a66d3fa71f..f3f90dbb85582e00ad6c3d950aed8dae83ee5b51 100644 (file)
@@ -5,7 +5,7 @@
    ESTADO: TERMINADO
 
 
-.. _ref_d:
+.. _d_lang:
 
 El lenguaje de programación D
 ============================================================================
@@ -15,109 +15,103 @@ 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:
 
-  Parece que la mayoría de los lenguajes de programación "nuevos" caen
-  en 2 categorías: aquellos académicos con nuevos paradigmas radicales y
-  aquellos de grandes corporaciones con el foco en el desarrollo rápido
-  y web. Tal vez es hora de que nazca un nuevo lenguaje de la experiencia
-  práctica implementando compiladores.
+   Parece que la mayoría de los lenguajes de programación "nuevos" caen en
+   2 categorías: aquellos académicos con nuevos paradigmas radicales
+   y aquellos de grandes corporaciones con el foco en el desarrollo rápido
+   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
+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
 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
@@ -125,29 +119,29 @@ 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.
+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.
 
 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,25 +149,25 @@ 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:
+
 
 
-.. _ref_d_generic:
+.. _d_generic:
 
 Programación genérica y meta-programación
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -181,519 +175,513 @@ 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::
+   Ejemplo::
 
-    static if ((void*).sizeof == 4)
-      pragma(msg, "32 bits");
+      static if ((void*).sizeof == 4)
+         pragma(msg, "32 bits");
 
-  Más información en http://www.digitalmars.com/d/1.0/version.html#staticif
+   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::
+   Ejemplo::
 
-    static i = 5;    // i es int
-    const d = 6.0;   // d es double
-    auto s = "hola"; // s es string (que es un alias de char[])
+      static i = 5;      // i es int
+      const d = 6.0;    // d es double
+      auto s = "hola"; // s es string (que es un alias de char[])
 
-  Más información en
-  http://www.digitalmars.com/d/1.0/declaration.html#AutoDeclaration
+   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::
+   Ejemplo::
 
-    typeof(5 + 6.0) d; // d es double
+      typeof(5 + 6.0) d; // d es double
 
-  Más información en http://www.digitalmars.com/d/1.0/declaration.html#typeof
+   Más información en http://www.digitalmars.com/d/1.0/declaration.html#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``.
+   cualquier tipo de colección (arreglos estáticos y dinámicos, arreglos
+   asociativos, clases, estructuras o delegados) puede ser iterada mediante la
+   sentencia ``foreach``.
 
-  Ejemplo::
+   Ejemplo::
 
-    int[] a = [ 1, 2, 3 ];
-    int total = 0;
-    foreach (i; a)
-      total += i;
+      int[] a = [ 1, 2, 3 ];
+      int total = 0;
+      foreach (i; a)
+         total += i;
 
 *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.
+   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.
 
-  Ejemplo::
+   Ejemplo::
 
-    T sumar(T)(T x, T y) { return x + y; }
-    auto i = sumar!(int)(5, 6);   // i == 11
-    auto f = sumar!(float)(5, 6); // j == 11.0f
+      T sumar(T)(T x, T y) { return x + y; }
+      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::
+   Ejemplo::
 
-    template bloque(T, U) {
-      T x;
-      U foo(T y);
-    }
+      template bloque(T, U) {
+         T x;
+         U foo(T y);
+      }
 
-    bloque!(int, float).x = 5;
-    float f = bloque!(int, float).foo(7);
+      bloque!(int, float).x = 5;
+      float f = bloque!(int, float).foo(7);
 
-  La utilidad más prominente de los bloques parametrizados se da al
-  acompañarse de *mixins*.
+   La utilidad más prominente de los bloques parametrizados se da al
+   acompañarse de *mixins*.
 
 Instanciación implícita de funciones parametrizadas:
-  el lenguaje es capaz de deducir los parámetros siempre que no hayan
-  ambigüedades
+   el lenguaje es capaz de deducir los parámetros siempre que no hayan
+   ambigüedades
 
-  Ejemplo::
+   Ejemplo::
 
-    auto i = sumar(5, 6);       // i == 11
-    auto f = sumar(5.0f, 6.0f); // f == 11.0f
+      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*:
-  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::
+   Ejemplo de especialización::
 
-    T sumar(T: int)(T x, T y) { return x + y + 1; }
-    auto i = sumar(5, 6);      // i == 12
-    auto f = sumar(5.0f, 6.0f) // f == 11.0f
+      T sumar(T: int)(T x, T y) { return x + y + 1; }
+      auto i = sumar(5, 6);         // i == 12
+      auto f = sumar(5.0f, 6.0f) // f == 11.0f
 
-  Ejemplo de especialización parcial::
+   Ejemplo de especialización parcial::
 
-    T sumar(T: T*)(T x, T y) { return *x + *y; }
-    int x = 5, y = 6;
-    auto i = sumar(&x, &y); // i == 11
-    float v = 5.0f, w = 6.0f;
-    auto f = sumar(&v, &w); // f == 11.0f
+      T sumar(T: T*)(T x, T y) { return *x + *y; }
+      int x = 5, y = 6;
+      auto i = sumar(&x, &y); // i == 11
+      float v = 5.0f, w = 6.0f;
+      auto f = sumar(&v, &w); // f == 11.0f
 
 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.
-
-  Ejemplo::
-
-    template hash(string s, uint so_far=0) {
-      static if (s.length == 0)
-        const hash = sofar;
-      else
-        const hash = hash!(s[1 .. length], sofar * 11 + s[0]);
-    }
-    string s = hash!("hola"); // calculado en tiempo de compilación
+   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.
+
+   Ejemplo::
+
+      template hash(string s, uint so_far=0) {
+         static if (s.length == 0)
+            const hash = sofar;
+         else
+            const hash = hash!(s[1 .. length], sofar * 11 + s[0]);
+      }
+      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::
+   Ejemplo::
 
-    double sumar(T...)(T t) {
-      double res = 0.0;
-      foreach (x; t)
-        res += x;
-      return res;
-    }
-    double d = sumar(1, 2.0, 3.0f, 4l); // d == 10.0
+      double sumar(T...)(T t) {
+         double res = 0.0;
+         foreach (x; t)
+            res += x;
+         return res;
+      }
+      double d = sumar(1, 2.0, 3.0f, 4l); // d == 10.0
 
 *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*.
-
-  Ejemplo::
-
-    int factorial(int n) {
-      if (n == 1)
-        return 1;
-      else
-        return n * factorial(n - 1);
-    }
-    static int x = factorial(5); // calculado en tiempo de compilación
-    int x = factorial(5); // calculado en tiempo de ejecución
-
-  Esta característica es vital para evitar la duplicación de código.
+   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*.
+
+   Ejemplo::
+
+      int factorial(int n) {
+         if (n == 1)
+            return 1;
+         else
+            return n * factorial(n - 1);
+      }
+      static int x = factorial(5); // calculado en tiempo de compilación
+      int x = factorial(5); // calculado en tiempo de ejecución
+
+   Esta característica es vital para evitar la duplicación de código.
 
 *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
-  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::
-
-    class A {
-      mixin bloque!(int, float);
-    }
-    A a = new A;
-    a.x = 5;
-    float f = a.foo(a.x);
-
-    class B {
-      mixin bloque!(long, double);
-    }
-    B b = new B;
-    b.x = 5l;
-    double d = a.foo(a.x);
-
-  *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.
-
-  Ejemplo::
-
-    string generar_sumar(string var_x, string var_y) {
-      return "return " ~ var_x ~ " + " ~ var_y ~ ";";
-    }
-
-    int sumar(int a, int b) {
-      mixin(generar_sumar!("a", b"));
-    }
-
-  Más información en http://www.digitalmars.com/d/1.0/mixin.html
+   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
+   introducida por la falta de herencia múltiple.
 
-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.
+   Ejemplo::
+
+      class A {
+         mixin bloque!(int, float);
+      }
+      A a = new A;
+      a.x = 5;
+      float f = a.foo(a.x);
+
+      class B {
+         mixin bloque!(long, double);
+      }
+      B b = new B;
+      b.x = 5l;
+      double d = a.foo(a.x);
 
-  Ejemplo::
+   *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.
+
+   Ejemplo::
+
+      string generar_sumar(string var_x, string var_y) {
+         return "return " ~ var_x ~ " + " ~ var_y ~ ";";
+      }
 
-    T foo(T)(T x) {
-      static if (is(T == class))
-        return new T;
-      else
-        return T.init;
-    }
+      int sumar(int a, int b) {
+         mixin(generar_sumar!("a", b"));
+      }
+
+   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.
+
+   Ejemplo::
+
+      T foo(T)(T x) {
+         static if (is(T == class))
+            return new T;
+         else
+            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
+   Más información en
+   http://www.digitalmars.com/d/1.0/expression.html#IsExpression
 
 
 
-.. _ref_d_low_level:
+.. _d_low_level:
 
 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.
+   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``.
+   al igual que C y C++, D_ provee la flexibilidad del uso de ``goto``.
 
-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)``.
+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)``.
 
-  Ejemplo::
+   .. [#abi] Interfaz de Aplicación Binaria (del inglés *Application Binary
+      Interface*).
 
-    extern (C) printf(const char* format, ...);
-    printf("3 + 5 == %d\n", 3 + 5); // llama al printf de C
+   Ejemplo::
+
+      extern (C) printf(const char* format, ...);
+      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
-  los servicios del sistema operativo o la biblioteca estándar de C.
+   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.
-
-  Esto también permite interoperar con C, ya que pueden definirse
-  ``structs`` y arreglos que pueden ser intercambiados con dicho lenguaje
-  sin problemas.
-
-  Ejemplo::
-
-    struct timeval {
-      time_t      tv_sec;
-      suseconds_t tv_usec;
-    }
-    extern (C) {
-      void* malloc(size_t);
-      size_t strlen(const char *);
-      int gettimeofday(timeval *, void *);
-    }
-    char* s = cast(char*) malloc(2);
-    s[0] = 'C';
-    s[1] = '\0';
-    size_t l = strlen(s); // l == 1
-    timeval tv;
-    gettimeofday(&tv, null);
+   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 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.
+
+   Ejemplo::
+
+      struct timeval {
+         time_t         tv_sec;
+         suseconds_t tv_usec;
+      }
+      extern (C) {
+         void* malloc(size_t);
+         size_t strlen(const char *);
+         int gettimeofday(timeval *, void *);
+      }
+      char* s = cast(char*) malloc(2);
+      s[0] = 'C';
+      s[1] = '\0';
+      size_t l = strlen(s); // l == 1
+      timeval tv;
+      gettimeofday(&tv, null);
 
 Rendimiento:
-  la :ref:`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.
+   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.
 
 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).
+   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:
-  Mediante ``align`` se puede especificar la alineación a tener en una
-  estructura.
+   Mediante ``align`` se puede especificar la alineación a tener en una
+   estructura.
 
-  Ejemplo::
-
-    align (1)
-    struct paquete_de_red {
-      char  tipo;
-      short valor;
-    }
-    // paquete_de_red.sizeof == 3
+   Ejemplo::
 
+      align (1)
+      struct paquete_de_red {
+         char   tipo;
+         short valor;
+      }
+      // paquete_de_red.sizeof == 3
 
-.. [#abi] Interfaz de Aplicación Binaria (del inglés *Application Binary
-   Interface*).
 
 
-.. _ref_d_high_level:
+.. _d_high_level:
 
 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:`ref_d_low_level`.
+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*.
+   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*.
 
 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).
+   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).
 
-  Ejemplo:
+   Ejemplo:
 
-  ``a.d``::
+   ``a.d``::
 
-    module a;
-    void f() {}
+      module a;
+      void f() {}
 
-  ``b.d``::
+   ``b.d``::
 
-    module b;
-    void f() {}
+      module b;
+      void f() {}
 
-  ``c.d``::
+   ``c.d``::
 
-      module c;
-      import a;
-      import b: f;
-      a.f();
-      b.f();
-      f(); // ejecuta b.f()
+         module c;
+         import a;
+         import b: f;
+         a.f();
+         b.f();
+         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++).
-
-  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.
-
-  Ejemplo::
-
-    bool buscar(T[] arreglo, T item, bool delegate(T x, T y) igual) {
-      foreach (t, arreglo)
-        if (igual(t, elemento))
-          return true;
-      return false;
-    }
-    struct Persona {
-      string nombre;
-    }
-    Persona[] personas;
-    // llenas personas
-    Persona p;
-    p.nombre = "Carlos";
-    bool encontrado = buscar(personas, p,
-                          (Persona x, Persona y) {
-                            return x.nombre == y.nombre;
-                          }
-                      );
+   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] Por ciudadano de primera clase se entiende que se trata
+      de un tipo soportado por completo por el lenguaje, disponiendo de
+      expresiones literales anónimas, pudiendo ser almacenados en variables,
+      estructuras de datos, teniendo una identidad intrínseca, más allá de un
+      nombre dado, etc. En realidad los arreglos asociativos no pueden ser
+      expresados como literales anónimos pero sí tienen una sintaxis especial
+      soportada directamente por el lenguaje.
+
+   Ejemplo::
+
+      bool buscar(T[] arreglo, T item, bool delegate(T x, T y) igual) {
+         foreach (t, arreglo)
+            if (igual(t, elemento))
+               return true;
+         return false;
+      }
+      struct Persona {
+         string nombre;
+      }
+      Persona[] personas;
+      // llenas personas
+      Persona p;
+      p.nombre = "Carlos";
+      bool encontrado = buscar(personas, p,
+                                       (Persona x, Persona y) {
+                                          return x.nombre == y.nombre;
+                                       }
+                                 );
 
 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*).
+   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*).
 
-  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.
+   Ambos son ciudadanos de primera clase, disponiendo de forma literal.
 
-  Ejemplo::
+   Ejemplo::
 
-    int[] primos = [ 2, 3, 5, 7, 11, 13, 17, 19 ];
-    primos ~= [ 23, 29 ];
-    auto menores_que_10 = primos[0..4]; // [ 2, 3, 5, 7 ]
-    int[string] agenda;
-    agenda["Pepe"] = 5555_1234;
+      int[] primos = [ 2, 3, 5, 7, 11, 13, 17, 19 ];
+      primos ~= [ 23, 29 ];
+      auto menores_que_10 = primos[0..4]; // [ 2, 3, 5, 7 ]
+      int[string] agenda;
+      agenda["Pepe"] = 5555_1234;
 
 *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``.
+   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``.
 
-  Ejemplo::
+   Ejemplo::
 
-    string s = "árbol";
+      string s = "árbol";
 
-    switch (s) {
-      case "árbol":
-        s = "tree";
-      default:
-        s = "";
-    }
+      switch (s) {
+         case "árbol":
+            s = "tree";
+         default:
+            s = "";
+      }
 
 ``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.
-
-  Ejemplo::
-
-    typedef int tipo;
-    int foo(tipo x) {}
-    tipo t = 10;
-    int i = 10;
-    foo(t);
-    foo(i); // error, no compila
-    alias tipo un_alias;
-    un_alias a = t;
-    foo(a);
+   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.
+
+   Ejemplo::
+
+      typedef int tipo;
+      int foo(tipo x) {}
+      tipo t = 10;
+      int i = 10;
+      foo(t);
+      foo(i); // error, no compila
+      alias tipo un_alias;
+      un_alias a = t;
+      foo(a);
 
 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
-  compilador pueda extraer esa información para generar un documento.
+   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
+   compilador pueda extraer esa información para generar un documento.
 
-  Más información en http://www.digitalmars.com/d/1.0/ddoc.html
+   Más información en http://www.digitalmars.com/d/1.0/ddoc.html
 
 Números complejos:
-  D_ soporta números complejos como ciudadanos de primera clase. Soporta
-  forma literal de números imaginarios y complejos.
+   D_ soporta números complejos como ciudadanos de primera clase. Soporta
+   forma literal de números imaginarios y complejos.
 
-  Ejemplo::
+   Ejemplo::
 
-    ifloat im = 5.0i;
-    float  re = 1.0;
-    cfloat c  = re + im; // c == 1.0 + 5.0i
-
-.. [#1stclasscity] Por ciudadano de primera clase se entiende que se
-   trata de un tipo soportado por completo por el lenguaje, disponiendo de
-   expresiones literales anónimas, pudiendo ser almacenados en variables,
-   estructuras de datos, teniendo una identidad intrínseca, más allá
-   de un nombre dado, etc. En realidad los arreglos asociativos no pueden
-   ser expresados como literales anónimos pero sí tienen una sintaxis
-   especial soportada directamente por el lenguaje.
+      ifloat im = 5.0i;
+      float   re = 1.0;
+      cfloat c   = re + im; // c == 1.0 + 5.0i
 
 
 
@@ -706,340 +694,342 @@ herramientas para soportar este paradigma de forma confiable. Entre las
 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]_.
-
-  D_ además soporta tipos de retorno covariantes para funciones virtuales.
-  Esto significa que una función sobreescrita por una clase derivada puede
-  retornar un tipo que sea derivado del tipo retornado por la función
-  original sobreescrita.
-
-  Ejemplo::
-
-    class A { }
-    class B : A { }
-
-    class Foo {
-      A test() { return null; }
-    }
+   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]_.
+
+   .. [#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.
+
+   D_ además soporta tipos de retorno covariantes para funciones virtuales.
+   Esto significa que una función sobreescrita por una clase derivada puede
+   retornar un tipo que sea derivado del tipo retornado por la función
+   original sobreescrita.
+
+   Ejemplo::
+
+      class A { }
+      class B : A { }
+
+      class Foo {
+         A test() { return null; }
+      }
 
-    class Bar : Foo {
-      B test() { return null; } // sobreescribe y es covariante con Foo.test()
-    }
+      class Bar : Foo {
+         B test() { return null; } // sobreescribe y es covariante con Foo.test()
+      }
 
-  Más información en http://www.digitalmars.com/d/1.0/function.html
+   Más información en http://www.digitalmars.com/d/1.0/function.html
 
 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.
+   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.
 
 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.
+   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:
-  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.
-
-  Ejemplo::
-
-    class Exterior {
-      int m;
-      class Anidada {
-        int foo() {
-          return m; // ok, puede acceder a un miembro de Exterior
-        }
+   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.
+
+   Ejemplo::
+
+      class Exterior {
+         int m;
+         class Anidada {
+            int foo() {
+               return m; // ok, puede acceder a un miembro de 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::
-
-    class Exterior {
-      int m;
-      static int n;
-      static class Anidada {
-        int foo() {
-          //return m; // error, miembro de Exterior
-          return n; // ok,  miembro estático de 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::
+
+      class Exterior {
+         int m;
+         static int n;
+         static class Anidada {
+            int foo() {
+               //return m; // error, miembro de Exterior
+               return n; // ok,   miembro estático de Exterior
+            }
+         }
       }
-    }
 
 
 Propiedades (*properties*):
-  en D_ se refiere a funciones miembro que pueden ser tratadas
-  sintácticamente como campos de esa clase/estructura.
-
-  Ejemplo::
-
-    class Foo {
-      int data() { return _data; } // propiedad de lectura
-      int data(int value) { return _data = value; } // de escritura
-      private int _data;
-    }
-    Foo f = new Foo;
-    f.data = 1;     // llama a f.data(1)
-    int i = f.data; // llama a f.data()
-
-  Además tipos nativos, clases, estructuras y expresiones tienen
-  *properties* predefinidos, por ejemplo:
-
-  ``sizeof``:
-    tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4).
-
-  ``init``:
-    valor de inicialización por omisión (ejemplo: ``float.init`` -> *NaN*
-    [#dnan]_).
-
-  ``stringof``:
-    representación textual del tipo (ejemplo: ``(1+2).stringof`` -> ``"1
-    + 2"``).
-
-  ``mangleof``:
-    representación textual del tipo *mutilado* [#dmangle]_.
-
-  ``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.
-
-  Más información sobre *properties* de clases en
-  http://www.digitalmars.com/d/1.0/property.html#classproperties
-  y sobre *properties* predefinidos en
-  http://www.digitalmars.com/d/1.0/property.html
-
-
-.. [#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.
-.. [#dnan] Del inglés *Not A Number*, es un valor especial que indica que
-   estamos ante un valor inválido.
-.. [#dmangle] *Name mangling* es el nombre dado comunmente a una técnica
-   necesaria para poder sobrecargar nombres de símbolos. Consiste en
-   codificar los nombres de las funciones tomando como entrada el nombre de
-   la función y la cantidad y tipo de parámetros, asegurando que dos
-   funciones con el mismo nombre pero distintos parámetros (sobrecargada)
-   tengan nombres distintos.
+   en D_ se refiere a funciones miembro que pueden ser tratadas
+   sintácticamente como campos de esa clase/estructura.
+
+   Ejemplo::
+
+      class Foo {
+         int data() { return _data; } // propiedad de lectura
+         int data(int value) { return _data = value; } // de escritura
+         private int _data;
+      }
+      Foo f = new Foo;
+      f.data = 1;       // llama a f.data(1)
+      int i = f.data; // llama a f.data()
+
+   Además tipos nativos, clases, estructuras y expresiones tienen
+   *properties* predefinidos, por ejemplo:
+
+   ``sizeof``:
+      tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4).
+
+   ``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"``).
+
+   ``mangleof``:
+      representación textual del tipo *mutilado* [#dmangle]_.
+
+   .. [#dmangle] *Name mangling* es el nombre dado comunmente a una técnica
+      necesaria para poder sobrecargar nombres de símbolos. Consiste en
+      codificar los nombres de las funciones tomando como entrada el nombre de
+      la función y la cantidad y tipo de parámetros, asegurando que dos
+      funciones con el mismo nombre pero distintos parámetros (sobrecargada)
+      tengan nombres distintos.
+
+   ``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.
+
+   Más información sobre *properties* de clases en
+   http://www.digitalmars.com/d/1.0/property.html#classproperties y sobre
+   *properties* predefinidos en
+   http://www.digitalmars.com/d/1.0/property.html
+
 
 
 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
-  silenciosamente sin ser detectados.
+   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.
+   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.
 
-  Ejemplo::
+   Ejemplo::
 
-    File f = open("archivo");
-    assert (f.ok());
+      File f = open("archivo");
+      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.
-
-  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):
+   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):
+
+   Pre y post condiciones:
+      Ejemplo::
+
+         double raiz_cuadrada(double x)
+         in { // pre-condiciones
+            assert (x >= 0.0);
+         }
+         out (resultado) { // post-condiciones
+            assert (resultado >= 0.0);
+            if (x < 1.0)
+               assert (resultado < x);
+            else if (x > 1.0)
+               assert (resultado > x);
+            else
+               assert (resultado == 1);
+         }
+         body {
+            // implementació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
+      pública y cuando se lo requiere de forma explícita utilizando
+      ``assert``.
+
+      Ejemplo::
+
+         class Fecha {
+               int dia;
+               int hora;
+               invariant() {
+                  assert(1 <= dia && dia <= 31);
+                  assert(0 <= hora && hora < 24);
+               }
+         }
+
+   Más información en http://www.digitalmars.com/d/1.0/dbc.html
 
-  ure y post condiciones:
-    Ejemplo::
+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()``.
 
-      double raiz_cuadrada(double x)
-      in { // pre-condiciones
-        assert (x >= 0.0);
-      }
-      out (resultado) { // post-condiciones
-        assert (resultado >= 0.0);
-        if (x < 1.0)
-          assert (resultado < x);
-        else if (x > 1.0)
-          assert (resultado > x);
-        else
-          assert (resultado == 1);
-      }
-      body {
-        // implementación
-      }
+   Ejemplo::
 
-  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``.
-
-    Ejemplo::
-
-      class Fecha {
-          int dia;
-          int hora;
-          invariant() {
-            assert(1 <= dia && dia <= 31);
-            assert(0 <= hora && hora < 24);
-          }
+      unittest {
+         Fecha fecha;
+         fecha.dia = 5;
+         assert (fecha.dia == 5);
+         assert (fecha);
       }
 
-  Más información en http://www.digitalmars.com/d/1.0/dbc.html
+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.
 
-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()``.
+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.
 
-  Ejemplo::
+   Ejemplo::
 
-    unittest {
-      Fecha fecha;
-      fecha.dia = 5;
-      assert (fecha.dia == 5);
-      assert (fecha);
-    }
+      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)
 
-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.
+*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.
 
-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.
+   Esta técnica es la base para desarrollar código seguro en cuanto
+   a excepciones (*exception-safe*) [SUTT99]_.
 
-  Ejemplo::
+   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.
 
-    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)
+   Ejemplo::
 
-*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.
-
-  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
-  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.
-
-  Ejemplo::
-
-    class Archivo {
-      this() { /* adquiere recurso */ }
-      ~this() { /* libera recurso */ }
-    }
-    void f() {
-      scope Archivo archivo = new Archivo;
-      // uso de archivo
-    } // en este punto se llama al destructor de archivo
+      class Archivo {
+         this() { /* adquiere recurso */ }
+         ~this() { /* libera recurso */ }
+      }
+      void f() {
+         scope Archivo archivo = new Archivo;
+         // uso de archivo
+      } // 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.
-
-  Ejemplo::
-
-    int f(Lock lock) {
-      lock.lock();
-      scope (exit)
-        lock.unlock();            // ejecutado siempre que salga de f()
-      auto trans = new Transaccion;
-      scope (success)
-        trans.commit();           // ejecutado si sale con "return"
-      scope (failure)
-        trans.rollback();         // ejecutado si sale por una excepción
-      if (condicion)
-        throw Exception("error"); // ejecuta 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()
-    }
-
-  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*.
+   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::
+
+      int f(Lock lock) {
+         lock.lock();
+         scope (exit)
+            lock.unlock();                  // ejecutado siempre que salga de f()
+         auto trans = new Transaccion;
+         scope (success)
+            trans.commit();                // ejecutado si sale con "return"
+         scope (failure)
+            trans.rollback();             // ejecutado si sale por una excepción
+         if (condicion)
+            throw Exception("error"); // ejecuta 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()
+      }
+
+   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::
-
-    class Foo {
-      synchronized void bar() { /* cuerpo */ }
-    }
-
-  Es equivalente a::
-
-    class Foo {
-      void bar() {
-        synchronized (this) { /* cuerpo */ }
+   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::
+
+      class Foo {
+         synchronized void bar() { /* cuerpo */ }
+      }
+
+   Es equivalente a::
+
+      class Foo {
+         void bar() {
+            synchronized (this) { /* cuerpo */ }
+         }
       }
-    }
 
 
 Compiladores
@@ -1050,53 +1040,53 @@ 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.
 
-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.
+.. [#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
+   representación intermedia que luego el *back-end* convierte a código de
+   máquina.
+
+.. [#backend] El *back-end* es la parte del compilador encargada de convertir
+   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.
 
 __ 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_.
 
 
-.. [#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
-   representación intermedia que luego el *back-end* convierte a código de
-   máquina.
-.. [#backend] El *back-end* es la parte del compilador encargada de
-   convertir la representación intermedia generada por el *front-end*
-   a código de máquina.
-
 
 .. include:: links.rst
 
-.. vim: set ts=2 sts=2 sw=2 et tw=75 :
+.. vim: set ts=3 sts=3 sw=3 et tw=78 :