]> git.llucax.com Git - z.facultad/75.00/informe.git/blobdiff - source/d.rst
Poner links de referencias como anónimos
[z.facultad/75.00/informe.git] / source / d.rst
index f916af0f20516a49228e9c479f9734a66d3fa71f..1fd5436e06810253f642cc0b342e0e03bd69aeca 100644 (file)
@@ -31,19 +31,19 @@ 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
@@ -52,11 +52,11 @@ 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*),
@@ -79,10 +79,10 @@ 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
+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
+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
@@ -125,7 +125,7 @@ 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
+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
@@ -197,230 +197,231 @@ 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::
+
+      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.
+
+   Ejemplo::
+
+      template bloque(T, U) {
+         T x;
+         U foo(T y);
+      }
 
-  Ejemplo::
+      bloque!(int, float).x = 5;
+      float f = bloque!(int, float).foo(7);
 
-    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
+   La utilidad más prominente de los bloques parametrizados se da al
+   acompañarse de *mixins*.
 
-  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.
+Instanciación implícita de funciones parametrizadas:
+   el lenguaje es capaz de deducir los parámetros siempre que no hayan
+   ambigüedades
 
-  Ejemplo::
+   Ejemplo::
 
-    template bloque(T, U) {
-      T x;
-      U foo(T y);
-    }
+      auto i = sumar(5, 6);          // i == 11
+      auto f = sumar(5.0f, 6.0f); // f == 11.0f
 
-    bloque!(int, float).x = 5;
-    float f = bloque!(int, float).foo(7);
+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 utilidad más prominente de los bloques parametrizados se da al
-  acompañarse de *mixins*.
+   Ejemplo de especialización::
 
-Instanciación implícita de funciones parametrizadas:
-  el lenguaje es capaz de deducir los parámetros siempre que no hayan
-  ambigüedades
+      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::
+   Ejemplo de especialización parcial::
 
-    auto i = sumar(5, 6);       // i == 11
-    auto f = sumar(5.0f, 6.0f); // 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
 
-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.
+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
 
-  Ejemplo de especializació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.
 
-    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::
 
-  Ejemplo de especialización parcial::
+      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
 
-    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
+*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
 
-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.
+   Esta característica es vital para evitar la duplicación de código.
 
-  Ejemplo::
+*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.
 
-    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
+   Ejemplo::
 
-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.
+      class A {
+         mixin bloque!(int, float);
+      }
+      A a = new A;
+      a.x = 5;
+      float f = a.foo(a.x);
 
-  Ejemplo::
+      class B {
+         mixin bloque!(long, double);
+      }
+      B b = new B;
+      b.x = 5l;
+      double d = a.foo(a.x);
 
-    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
+   *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.
 
-*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.
+   Ejemplo::
 
-*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
+      string generar_sumar(string var_x, string var_y) {
+         return "return " ~ var_x ~ " + " ~ var_y ~ ";";
+      }
 
-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.
+      int sumar(int a, int b) {
+         mixin(generar_sumar!("a", b"));
+      }
 
-  Ejemplo::
+   Más información en http://www.digitalmars.com/d/1.0/mixin.html
 
-    T foo(T)(T x) {
-      static if (is(T == class))
-        return new T;
-      else
-        return T.init;
-    }
+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
 
 
 
@@ -436,90 +437,90 @@ 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)``.
+   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::
+   Ejemplo::
 
-    extern (C) printf(const char* format, ...);
-    printf("3 + 5 == %d\n", 3 + 5); // llama al printf de C
+      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 alocar 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 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);
 
 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:`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::
+   Ejemplo::
 
-    align (1)
-    struct paquete_de_red {
-      char  tipo;
-      short valor;
-    }
-    // paquete_de_red.sizeof == 3
+      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*).
+    Interface*).
 
 
 .. _ref_d_high_level:
@@ -538,162 +539,162 @@ 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.
+
+   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
+      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.
+    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.
 
 
 
@@ -706,127 +707,128 @@ 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]_.
+
+   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.
+   en D_ se refiere a funciones miembro que pueden ser tratadas
+   sintácticamente como campos de esa clase/estructura.
 
-  Ejemplo::
+   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()
+      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:
+   Además tipos nativos, clases, estructuras y expresiones tienen
+   *properties* predefinidos, por ejemplo:
 
-  ``sizeof``:
-    tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4).
+   ``sizeof``:
+      tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4).
 
-  ``init``:
-    valor de inicialización por omisión (ejemplo: ``float.init`` -> *NaN*
-    [#dnan]_).
+   ``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"``).
+   ``stringof``:
+      representación textual del tipo (ejemplo: ``(1+2).stringof`` -> ``"1
+      + 2"``).
 
-  ``mangleof``:
-    representación textual del tipo *mutilado* [#dmangle]_.
+   ``mangleof``:
+      representación textual del tipo *mutilado* [#dmangle]_.
 
-  ``alignof``
-    alineación de una estructura o tipo.
+   ``alignof``
+      alineación de una estructura o tipo.
 
-  Estos son solo los *properties* predefinidos para todos los tipos, pero
-  hay una cantidad considerable de *properties* extra para cada tipo.
+   Estos son solo los *properties* predefinidos para todos los tipos, pero
+   hay una cantidad considerable de *properties* extra para cada tipo.
 
-  Más información sobre *properties* de clases en
-  http://www.digitalmars.com/d/1.0/property.html#classproperties
-  y sobre *properties* predefinidos en
-  http://www.digitalmars.com/d/1.0/property.html
+   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
@@ -859,187 +861,189 @@ 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.
+   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
 
-  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):
-
-  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
@@ -1099,4 +1103,4 @@ se terminó desarrollando el trabajo utilizando LDC_.
 
 .. 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 :