]> git.llucax.com Git - z.facultad/75.00/informe.git/blob - source/d.rst
Aclarar qué variables son globales en copying collector
[z.facultad/75.00/informe.git] / source / d.rst
1
2 .. highlight:: d
3
4 .. _d_lang:
5
6 El lenguaje de programación D
7 ============================================================================
8
9
10 Historia
11 ----------------------------------------------------------------------------
12
13 D_ es un lenguaje de programación relativamente joven. Nació en 1999 y el
14 2 de enero de 2007 salió su `versión 1.0`__. Poco tiempo después se continúo
15 el desarrollo del lenguaje en la `versión 2.0`__, que pasó a ser considerada
16 estable aproximadamente en junio de 2010 con el lanzamiento del libro "The
17 D Programming Language" [ALX10]_, pero aún es un trabajo en progreso.
18
19 __ `D 1.0`_
20 __ `D 2.0`_
21
22 El lenguaje fue diseñado e implementado por `Walter Bright`_, desarrollador
23 principal de Zortech C++, uno de los primeros compiladores de C++ que
24 compilaba a código nativo, y está fuertemente influenciado por éste. Sin
25 embargo toma muchos conceptos de otros lenguajes de más alto nivel, como Java_
26 o incluso lenguajes dinámicos como Perl_, Python_ y Ruby_.
27
28 El origen del lenguaje está plasmado en su sitio web, en donde se cita
29 [DWEB]_:
30
31    It seems to me that most of the "new" programming languages fall into one
32    of two categories: Those from academia with radical new paradigms and those
33    from large corporations with a focus on RAD and the web. Maybe it's time
34    for a new language born out of practical experience implementing compilers.
35
36 Esto podría traducirse como:
37
38    Parece que la mayoría de los lenguajes de programación "nuevos" caen en
39    2 categorías: aquellos académicos con nuevos paradigmas radicales
40    y aquellos de grandes corporaciones con el foco en el desarrollo rápido
41    y web. Tal vez es hora de que nazca un nuevo lenguaje de la experiencia
42    práctica implementando compiladores.
43
44 La versión 1.0 fue más bien una etiqueta arbitraria que un indicador real de
45 estabilidad y completitud. Luego de liberarse se siguieron agregando nuevas
46 características al lenguaje hasta que se empezó el desarrollo en paralelo de
47 la versión 2.0 al introducirse el concepto de inmutabilidad y funciones
48 *puras* [#dpure]_ (a mediados de 2007).
49
50 .. [#dpure] Por funciones *puras* en D_ se entiende que no tienen efectos
51    colaterales. Es decir, una función pura siempre que se llame con la misma
52    entrada producirá el mismo resultado. Esto es análogo a como funcionan los
53    lenguajes funcionales en general, abriendo la puerta a la programación de
54    estilo funcional en D_.
55
56 A partir de este momento la versión 1.0 quedó *teóricamente* congelada,
57 introduciendo solo cambios que arreglen errores (*bug fixes*), agregando
58 nuevas características solamente en la versión 2.0 del lenguaje. La realidad
59 es que se hicieron cambios incompatibles a la versión 1.0 del lenguaje en
60 reiteradas ocasiones, pero se fue tendiendo a cada vez introducir menos
61 cambios incompatibles. Sin embargo al día de hoy el compilador de referencia
62 sigue teniendo algunas características presentes en la especificación del
63 lenguaje sin implementar, por lo que todavía no hay una implementación
64 completa de la versión 1.0 del lenguaje.
65
66 El lenguaje ha sido, hasta el desarrollo de la versión 2.0 al menos, un
67 esfuerzo unipersonal de `Walter Bright`_, dados sus problemas a la hora de
68 delegar o aceptar contribuciones. Esto motivó a la comunidad de usuarios de D_
69 a crear bibliotecas base alternativas a la estándar (llamada Phobos_) en las
70 cuales se pudiera trabajar sin las trabas impuestas por el autor del lenguaje.
71
72 En este contexto nacen primero Mango_ y luego Ares_. Mango_ fue creada por
73 Kris Macleod Bell a principios de 2004 como una biblioteca que provee
74 servicios básicos de entrada/salida (o *I/O* de *input/output* en inglés) de
75 alto rendimiento.   Siendo estos servicios algo básico lo más natural hubiera
76 sido que se encuentren en la biblioteca estándar de D_ pero por las
77 dificultades para contribuir a ésta, se desarrolla como una biblioteca
78 separada.   A mediados de 2004 Sean Kelly crea Ares_ , con las mismas
79 motivaciones pero con la intención de crear una biblioteca base (conocida en
80 inglés como *runtime*) que incluye los servicios básicos que necesita el
81 lenguaje (información de tipos, manejo de excepciones e hilos, creación
82 y manipulación de objetos, recolector de basura, etc.). Al poco tiempo de
83 liberarse Ares_, Mango_ empieza a utilizarla como biblioteca base.
84
85 Para comienzos de 2006, se empieza a trabajar en la combinación de ambas
86 bibliotecas para lograr una biblioteca estándar alternativa con un alto grado
87 de cohesión. Finalmente a principios de 2007, coincidiendo por casualidad con
88 la aparición de `D 1.0`_, se anuncia el resultado de este combinación bajo el
89 nombre de Tango_, proveyendo una alternativa completa y madura a la biblioteca
90 estándar de D_ Phobos_.  A principios de 2008 los principales desarrolladores
91 de Tango_ (Kris Bell, Sean Kelly, Lars Ivar Igesund y Michael Parker) publican
92 el libro llamado `Learn to Tango with D`_ [BKIP08]_.
93
94 Esto por un lado fue un gran avance porque dio un impulso muy considerable al
95 lenguaje pero por otro un gran retroceso, porque todavía al día de hoy `D
96 1.0`_ tiene dos bibliotecas base, una estándar pero de peor calidad, menos
97 mantenida y usada; y una alternativa de mayor calidad y apertura a la
98 comunidad (pero no estándar). El peor problema es que ambas son
99 **incompatibles**, por lo que un programa hecho con Tango_ no funciona con
100 Phobos_ y viceversa (a menos que el programador haya invertido una cantidad de
101 tiempo considerable en asegurarse que funcione con ambas).
102
103 Esto hace que la compatibilidad de programas y bibliotecas esté muy
104 fragmentada entre las dos bibliotecas base. Si bien no parece que vaya a haber
105 solución alguna a este problema para `D 1.0`_, `D 2.0`_ va en camino
106 a solucionar este problema ya que utiliza DRuntime_, un nuevo intento de Sean
107 Kelly por proveer una biblioteca *runtime* bien organizada y mantenida, que es
108 una adaptación de la biblioteca *runtime* de Tango_ a `D 2.0`_. Sin embargo
109 Tango_ no fue adaptada a `D 2.0`_ todavía, y no hay muchas perspectivas de que
110 sea portada en algún momento, por un lado porque en general la comunidad sigue
111 fragmentada entre muchos usuarios de `D 1.0`_ que no están contentos con los
112 cambios introducidos en `D 2.0`_, en su mayoría usuarios de Tango_, y que no
113 planean migrar a esa versión; y por otro porque el desarrollo de Phobos_ 2.0
114 se ha abierto mucho y tiene muchos colaboradores, por lo tanto la mayor parte
115 de la gente que utiliza `D 2.0`_ está contenta con el estado de Phobos_ 2.0.
116
117
118 Descripción general
119 ----------------------------------------------------------------------------
120
121 D_ es un lenguaje de programación con sintaxis tipo C, multi-paradigma,
122 compilado, con *tipado* fuerte y estático, buenas capacidades tanto de
123 programación de bajo nivel (*system programming*) como de alto nivel; además
124 es compatible de forma binaria con C (se puede enlazar código objeto C con
125 código objeto D). Con estas características, D_ logra llenar un vacío
126 importante que hay entre lo lenguajes de alto bajo nivel y los de alto nivel
127 [BKIP08]_. Si bien tiene herramientas de muy bajo nivel, que por lo tanto son
128 muy propensas a errores, da una infinidad de mecanismos para evitar el uso de
129 estas herramientas a menos que sea realmente necesario.  Además pone mucho
130 énfasis en la programación confiable, para lo cual provee muchos mecanismos
131 para detectar errores en los programas de forma temprana.
132
133 Si puede pensarse en C++ como un "mejor C", podría decirse que D_ es un "mejor
134 C++", ya que el objetivo del lenguaje es muy similar a C++, pero implementa
135 muchas características que jamás pudieron entrar en el estándar de C++ y lo
136 hace de una forma mucho más limpia, ya que no debe lidiar con problemas de
137 compatibilidad hacia atrás, y cuenta con la experiencia del camino recorrido
138 por C++, pudiendo extraer de él los mejores conceptos pero evitando sus
139 mayores problemas.
140
141 Una gran diferencia con C++ es que el análisis sintáctico (*parsing*) se puede
142 realizar sin ningún tipo de análisis semántico, dado que a diferencia de éstos
143 su gramática es libre de contexto (*context-free grammar*). Esto acelera
144 y simplifica considerablemente el proceso de compilación [WBB10]_ [DWOV]_.
145
146 Otra gran diferencia es que D_ decide incluir recolección de basura como parte
147 del lenguaje, mientras que en el comité de estandarización de C++ nunca se
148 llegó a un consenso para su incorporación.
149
150
151 Características del lenguaje
152 ----------------------------------------------------------------------------
153
154 A continuación se enumeran las principales características de D_, agrupadas
155 por unidades funcionales o paradigmas que soporta [DWLR]_:
156
157
158
159 .. _d_generic:
160
161 Programación genérica y meta-programación
162 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163
164 La programación genérica se trata de la capacidad de poder desarrollar
165 algoritmos y estructuras independientes de los tipos que manipulan (pero de
166 forma segura o *type-safe*). Esto fue muy popularizado por C++ gracias a su
167 soporte de plantillas (*templates*) y luego otros lenguajes como Java_ y `C#`_
168 lo siguieron. Sin embargo otros lenguajes proveen formas más avanzadas de
169 programación genérica, gracias a sistemas de tipos más complejos (como
170 Haskell_).
171
172 La meta-programación se refiere en general a la capacidad de un lenguaje para
173 permitir generar código dentro del mismo programa de forma automática.  Esto
174 permite evitar duplicación de código y fue también muy popularizado por el
175 soporte de *templates* de C++, aunque muchos otros lenguajes tienen mejor
176 soporte de meta-programación, en especial los lenguajes dinámicos (como
177 Python_).
178
179 D_ provee las siguientes herramientas para realizar programación genérica
180 y meta-programación:
181
182 ``if`` estático (``static if``)
183    Esta construcción es similar a la directiva del preprocesador de C/C++
184    ``#if``, pero a diferencia de éste, el ``static if`` de D_ tiene acceso
185    a todos los símbolos del compilador (constantes, tipos, variables, etc)
186    [DWSI]_.
187
188    Ejemplo::
189
190       static if ((void*).sizeof == 4)
191          pragma(msg, "32 bits");
192
193 Inferencia de tipos básica implícita y explícita (mediante ``typeof``)
194    Si no se especifica un tipo al declarar una variable, se infiere a partir
195    del tipo de su valor de inicialización [DWIN]_.
196
197    Ejemplo::
198
199       static i = 5;      // i es int
200       const d = 6.0;    // d es double
201       auto s = "hola"; // s es string (que es un alias de char[])
202
203    Mediante el uso de ``typeof`` se puede solicitar el tipo de una expresión
204    arbitraria [DWTO]_.
205
206    Ejemplo::
207
208       typeof(5 + 6.0) d; // d es double
209
210 Iteración sobre colecciones (``foreach``)
211    Cualquier tipo de colección (arreglos estáticos y dinámicos, arreglos
212    asociativos, clases, estructuras o delegados) puede ser iterada mediante la
213    sentencia ``foreach`` [DWFE]_.
214
215    Ejemplo::
216
217       int[] a = [ 1, 2, 3 ];
218       int total = 0;
219       foreach (i; a)
220          total += i;
221
222 *Templates*
223    Tanto clases como funciones pueden ser generalizadas. Esto permite desarrollar
224    algoritmos genéricos sin importar el tipo de los datos de entrada, siempre
225    y cuando todos los tipos tengan una *interfaz* común.   Esto también es
226    conocido como *polimorfismo en tiempo de compilación*, y es la forma más
227    básica de programación genérica [DWTP]_.
228
229    Ejemplo::
230
231       T sumar(T)(T x, T y) { return x + y; }
232       auto i = sumar!(int)(5, 6);    // i == 11
233       auto f = sumar!(float)(5, 6); // j == 11.0f
234
235    Además se pueden definir bloques de declaraciones generalizadas (esto no
236    es posible en C++), permitiendo instanciar dicho bloque con parámetros
237    particulares. Esto sirve como un mecanismo para la reutilización de código,
238    ya que puede incluirse un mismo bloque en distintos lugares (por ejemplo
239    clases). Un bloque generalizado puede verse como una especie de módulo.
240
241    Ejemplo::
242
243       template bloque(T, U) {
244          T x;
245          U foo(T y);
246       }
247
248       bloque!(int, float).x = 5;
249       float f = bloque!(int, float).foo(7);
250
251    La utilidad más prominente de los bloques generalizados se da al
252    acompañarse de *mixins*.
253
254    Además las *templates* de D_ tienen las siguientes características
255    destacables:
256
257    Instanciación implícita de funciones generalizadas
258       El lenguaje es capaz de deducir los parámetros siempre que no hayan
259       ambigüedades.
260
261       Ejemplo::
262
263          auto i = sumar(5, 6);          // i == 11
264          auto f = sumar(5.0f, 6.0f); // f == 11.0f
265
266    Especialización explícita y parcial de *templates*
267       La especialización de *templates* consiste, al igual que en C++, en
268       proveer una implementación especializada para un tipo de dato (o valor)
269       de los parámetros.   Especialización parcial se refiere a la capacidad
270       de especializar un parámetro a través de un subtipo. Por ejemplo, se
271       puede especializar un *template* para cualquier tipo de puntero, o para
272       cualquier tipo de arreglo dinámico, sin necesidad de especificar el tipo
273       al que apunta dicho puntero o el tipo almacenado por el arreglo.
274
275       Ejemplo de especialización::
276
277          T sumar(T)(T x, T y)      { return x + y; }
278          T sumar(T: int)(T x, T y) { return x + y + 1; }
279          auto i = sumar(5, 6);         // i == 12
280          auto f = sumar(5.0f, 6.0f) // f == 11.0f
281
282       Ejemplo de especialización parcial::
283
284          T sumar(T)(T x, T y)     { return x + y; }
285          T sumar(T: T*)(T x, T y) { return *x + *y; }
286          int x = 5, y = 6;
287          auto i = sumar(&x, &y); // i == 11
288          float v = 5.0f, w = 6.0f;
289          auto f = sumar(&v, &w); // f == 11.0f
290
291    Tipos, valores (incluyendo *strings*) y *templates* como parámetros
292       Este es otro bloque de construcción importantísimo para la programación
293       genérica en D, ya que combinando *templates* que toman *strings* como
294       parámetro en combinación con *string mixins* pueden hacerse toda clase
295       de meta-programas.
296
297       Ejemplo::
298
299          template hash(string s, uint so_far=0) {
300             static if (s.length == 0)
301                const hash = so_far;
302             else
303                const hash = hash!(s[1 .. length], so_far * 11 + s[0]);
304          }
305          string s = hash!("hola"); // calculado en tiempo de compilación
306
307    Cantidad de parámetros variables para *templates*
308       Esta característica permite implementar tuplas y otros algoritmos que
309       inherentemente deben tomar una cantidad variable de parámetros en tiempo
310       de compilación.
311
312       Ejemplo::
313
314          double sumar(T...)(T t) {
315             double res = 0.0;
316             foreach (x; t)
317                res += x;
318             return res;
319          }
320          double d = sumar(1, 2.0, 3.0f, 4l); // d == 10.0
321
322 *CTFE* (*compile-time function execution*)
323    Si una función cumple ciertas reglas básicas (como por ejemplo no tener
324    efectos colaterales) puede ser ejecutada en tiempo de compilación en vez de
325    tiempo de ejecución. Esto permite hacer algunos cálculos que no cambian de
326    ejecución en ejecución al momento de compilar, mejorando el rendimiento
327    o permitiendo formas avanzadas de meta-programación. Esta característica se
328    vuelve particularmente útil al combinarse con *string mixins* [DWCF]_.
329
330    Ejemplo::
331
332       int factorial(int n) {
333          if (n == 1)
334             return 1;
335          else
336             return n * factorial(n - 1);
337       }
338       static int x = factorial(5); // calculado en tiempo de compilación
339       int x = factorial(5); // calculado en tiempo de ejecución
340
341    Esta característica es muy importante para evitar la duplicación de código.
342
343 *Mixins*, incluyendo *string mixins*
344    La palabra *mixin* tiene significados distintos en varios lenguajes de
345    programación. En D_ *mixin* significa tomar una secuencia arbitraria de
346    declaraciones e insertarla en el contexto (*scope*) actual. Esto puede
347    realizarse a nivel global, en clases, estructuras o funciones. Esto sirve
348    como un mecanismo para evitar duplicación de código que puede ser
349    introducida por la falta de herencia múltiple [DWMT]_.
350
351    Ejemplo::
352
353       class A {
354          mixin bloque!(int, float);
355       }
356       A a = new A;
357       a.x = 5;
358       float f = a.foo(a.x);
359
360       class B {
361          mixin bloque!(long, double);
362       }
363       B b = new B;
364       b.x = 5l;
365       double d = a.foo(a.x);
366
367    *String mixin* se refiere a la capacidad de *incrustar* un *string* que
368    contenga un fragmento de código en un programa como si este fragmento
369    hubiera sido escrito en el código fuente directamente por el programador.
370    Esto permite hacer manipulaciones arbitrariamente complejas en combinación
371    con funciones ejecutadas en tiempo de compilación [DWME]_ [DWMX]_.
372
373    Ejemplo::
374
375       string generar_sumar(string var_x, string var_y) {
376          return "return " ~ var_x ~ " + " ~ var_y ~ ";";
377       }
378
379       int sumar(int a, int b) {
380          mixin(generar_sumar!("a", "b"));
381       }
382
383 Expresiones ``is``
384    Las *expresiones ``is``* permiten la compilación condicional basada en las
385    características de un tipo [DWIE]_.
386
387    Ejemplo::
388
389       T foo(T)(T x) {
390          static if (is(T == class))
391             return new T;
392          else
393             return T.init;
394       }
395
396    Esto provee además una forma simple de reflexión en tiempo de compilación.
397
398
399
400 .. _d_low_level:
401
402 Programación de bajo nivel (*system programming*)
403 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
404
405 Por programación de bajo nivel nos referimos a la capacidad de un lenguaje de
406 manipular el hardware directamente, o al menos la memoria. C es probablemente
407 el lenguaje de bajo nivel más popular, seguido por C++.
408
409 D_ presenta muchas características de bajo nivel:
410
411 Compila a código de máquina nativo
412    Los programas generados por D_ no son interpretados ni necesitan una
413    máquina virtual como otros lenguajes de más alto nivel como Java_, `C#`_,
414    Python_, etc [DWOV]_.
415
416 *Assembly* empotrado
417    Provee acceso directo al *hardware* y la posibilidad de utilizar cualquier
418    característica de éste que no esté disponible en el lenguaje.
419
420    Una ventaja sobre C y C++ es que el lenguaje *assembly* utilizado dentro de
421    D_ está especificado, por lo que se puede mantener la portabilidad entre
422    compiladores incluso cuando se utiliza *assembly* (mientras que no se
423    cambie de arquitectura, por supuesto) [DWIA]_.
424
425 ``goto``
426    Al igual que C y C++, D_ provee la flexibilidad del uso de ``goto``
427    [DWGT]_.
428
429 Compatibilidad con C
430    Soporta todos los tipos de C y es ABI [#abi]_ compatible con éste. Esto
431    permite enlazar archivos objeto estándar de C y D_ en un mismo programa.
432    Además permite interoperar con C a través de ``extern (C)`` [DWCC]_.
433
434    .. [#abi] Interfaz de Aplicación Binaria (del inglés *Application Binary
435       Interface*).
436
437    Ejemplo::
438
439       extern (C) printf(const char* format, ...);
440       printf("3 + 5 == %d\n", 3 + 5); // llama al printf de C
441
442 Manejo de memoria explícito
443    Permite asignar estructuras en el *stack* o en el *heap*, haciendo uso de
444    los servicios del sistema operativo o la biblioteca estándar de C [DWMM]_.
445
446 Objetos y arreglos *livianos*
447    Por objetos *livianos* se entiende no-polimórficos. Es decir, un
448    agrupamiento de variables análogo al ``struct`` de C, sin tabla virtual ni
449    otro tipo de *overhead*. Los arreglos *livianos* son arreglos estáticos
450    como en C, cuyo tamaño es fijo, también sin ningún tipo de *overhead* como
451    C. Además puede asignarse un arreglo dinámicamente usando ``malloc()``
452    y utilizar el operador ``[]`` para accederlo [DWST]_ [DWCL]_.
453
454    Esto también permite interoperar con C, ya que pueden definirse ``structs``
455    y arreglos que pueden ser intercambiados con dicho lenguaje sin problemas.
456
457    Ejemplo::
458
459       struct timeval {
460          time_t         tv_sec;
461          suseconds_t tv_usec;
462       }
463       extern (C) {
464          void* malloc(size_t);
465          size_t strlen(const char *);
466          int gettimeofday(timeval *, void *);
467       }
468       char* s = cast(char*) malloc(2);
469       s[0] = 'C';
470       s[1] = '\0';
471       size_t l = strlen(s); // l == 1
472       timeval tv;
473       gettimeofday(&tv, null);
474
475 Rendimiento
476    La :ref:`d_generic` permite realizar muchas optimizaciones ya que se
477    resuelve en tiempo de compilación y por lo tanto aumenta el rendimiento en
478    la ejecución [DWTP]_.
479
480 Número de punto flotante de 80 bits
481    El tipo ``real`` de D_ tiene precisión de 80 bits si la plataforma lo
482    soporta (por ejemplo en i386) [DWTY]_.
483
484 Control de alineación de miembros de una estructura
485    Mediante ``align`` se puede especificar la alineación a tener en una
486    estructura [DWAL]_.
487
488    Ejemplo::
489
490       align (1)
491       struct paquete_de_red {
492          char   tipo;
493          short valor;
494       }
495       // paquete_de_red.sizeof == 3
496
497
498
499 .. _d_high_level:
500
501 Programación de alto nivel
502 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
503
504 Programación de alto nivel se refiere a construcciones más avanzadas que una
505 sentencia para iterar; expresiones con una semántica más ricas que proveen de
506 mayor expresividad al programador o le permiten focalizarse de mejor manera
507 en los algoritmos independizándose del *hardware* o de como funciona una
508 computadora. Es exactamente el opuesto a :ref:`d_low_level`.
509
510 En general estas características tienen como efecto secundario una mejora de la
511 productividad de los programadores. D_ adopta herramientas de muchos lenguajes
512 de alto nivel, como Java_ y Python_, por ejemplo:
513
514 Manejo automático de memoria
515    Al igual que C/C++ y prácticamente cualquier lenguaje imperativo maneja
516    automáticamente el *stack*, pero a diferencia de la mayoría de los
517    lenguajes de bajo nivel, D_ permite manejar el *heap* de manera automática
518    también a través de un *recolector de basura* [DWGC]_.
519
520 Sistema de paquetes y módulos (similar a Java_ o Python_)
521    Un módulo es una unidad que agrupa clases, funciones y cualquier otra
522    construcción de lenguaje. Un paquete es una agrupación de módulos. D_
523    asocia un módulo a un archivo fuente (y un archivo objeto cuando éste es
524    compilado) y un paquete a un directorio. A diferencia de C/C++ no necesita
525    de un preprocesador para incluir declaraciones de otros *módulos* (en C/C++
526    no existe el concepto de módulo, solo de unidades de compilación) [DWMO]_.
527
528    Ejemplo:
529
530    ``a.d``::
531
532       module a;
533       void f() {}
534
535    ``b.d``::
536
537       module b;
538       void f() {}
539
540    ``c.d``::
541
542          module c;
543          import a;
544          import b: f;
545          a.f();
546          b.f();
547          f(); // ejecuta b.f()
548
549 Funciones y delegados
550    Las funciones pueden ser sobrecargadas (funciones con el mismo nombre pero
551    distinta cantidad o tipo de parámetros), pueden especificarse argumentos de
552    entrada, salida o entrada/salida, argumentos por omisión o argumentos
553    evaluados de forma perezosa (*lazy*). Además pueden tener una cantidad de
554    argumentos variables pero manteniendo información de tipos (más seguro que
555    C/C++) [DWFU]_.
556
557    Los *delegados* son punteros a función con un contexto asociado. Este
558    contexto puede ser un objeto (en cuyo caso la función es un método) o un
559    *stack frame* (en cuyo caso la función es una función anidada).
560
561    Además de esto los delegados son ciudadanos de primera clase
562    [#1stclasscity]_, disponiendo de forma literal (delegado anónimo), lo que
563    permite construcciones de alto nivel muy conveniente. Los argumentos
564    evaluados de forma perezosa no son más que un delegado que se ejecuta solo
565    cuando es necesario.
566
567    .. [#1stclasscity] Por ciudadano de primera clase se entiende que se trata
568       de un tipo soportado por completo por el lenguaje, disponiendo de
569       expresiones literales anónimas, pudiendo ser almacenados en variables,
570       estructuras de datos, teniendo una identidad intrínseca, más allá de un
571       nombre dado, etc. En realidad los arreglos asociativos no pueden ser
572       expresados como literales anónimos pero sí tienen una sintaxis especial
573       soportada directamente por el lenguaje.
574
575    Ejemplo::
576
577       bool buscar(T[] arreglo, T item, bool delegate(T x, T y) igual) {
578          foreach (t, arreglo)
579             if (igual(t, item))
580                return true;
581          return false;
582       }
583       struct Persona {
584          string nombre;
585       }
586       Persona[] personas;
587       // llenas personas
588       Persona p;
589       p.nombre = "Carlos";
590       bool encontrado = buscar(personas, p,
591                                        (Persona x, Persona y) {
592                                           return x.nombre == y.nombre;
593                                        }
594                                  );
595
596 Arreglos *dinámicos* y arreglos asociativos
597    Los arreglos *dinámicos* son arreglos de longitud variable manejados
598    automáticamente por el lenguaje (análogos al ``std::vector`` de C++).
599    Soportan concatenación (a través del operador ``~``), rebanado o *slicing*
600    (a través del operador ``[x..y]``) y chequeo de límites (*bound checking*)
601    [DWAR]_.
602
603    Los arreglos asociativos (también conocidos como *hashes* o diccionarios)
604    también son provistos por el lenguaje [DWAA]_.
605
606    Ambos son ciudadanos de primera clase, disponiendo de forma literal.
607
608    Ejemplo::
609
610       int[] primos = [ 2, 3, 5, 7, 11, 13, 17, 19 ];
611       primos ~= [ 23, 29 ];
612       auto menores_que_10 = primos[0..4]; // [ 2, 3, 5, 7 ]
613       int[string] agenda;
614       agenda["Pepe"] = 5555_1234;
615
616 *Strings*
617    Al igual que los delegados y arreglos dinámicos y asociativos, los
618    *strings* son ciudadanos de primera clase, teniendo forma literal y siendo
619    codificados en UTF-8/16/32. Son un caso particular de arreglo dinámico y es
620    posible utilizarlos en sentencias ``switch``/``case`` [DWSR]_.
621
622    Ejemplo::
623
624       string s = "árbol";
625
626       switch (s) {
627          case "árbol":
628             s = "tree";
629          default:
630             s = "";
631       }
632
633 ``typedef`` y ``alias``
634    El primero define un nuevo tipo basado en otro. A diferencia de C/C++ el
635    tipo original no puede ser implícitamente convertido al tipo nuevo (excepto
636    valores literales), pero la conversión es válida en el otro sentido
637    (similar a los ``enum`` en C++). Por el contrario, ``alias`` es análogo al
638    ``typedef`` de C/C++ y simplemente es una forma de referirse al mismo tipo
639    con un nombre distinto [DWDC]_.
640
641    Ejemplo::
642
643       typedef int tipo;
644       int foo(tipo x) {}
645       tipo t = 10;
646       int i = 10;
647       foo(t);
648       foo(i); // error, no compila
649       alias tipo un_alias;
650       un_alias a = t;
651       foo(a);
652
653 Documentación embebida
654    D_ provee un sistema de documentación embebida, análogo a lo que proveen
655    Java_ o Python_ en menor medida. Hay comentarios especiales del código que
656    pueden ser utilizados para documentarlo de forma tal que luego el
657    compilador pueda extraer esa información para generar un documento [DWDO]_.
658
659 Números complejos
660    D_ soporta números complejos como ciudadanos de primera clase. Soporta
661    forma literal de números imaginarios y complejos [DWTY]_.
662
663    Ejemplo::
664
665       ifloat im = 5.0i;
666       float   re = 1.0;
667       cfloat c   = re + im; // c == 1.0 + 5.0i
668
669
670
671 Programación orientada a objetos
672 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
673
674 La orientación a objetos es probablemente el paradigma más utilizado en la
675 actualidad a la hora de diseñar e implementar un programa. D_ provee muchas
676 herramientas para soportar este paradigma de forma confiable. Entre las
677 características más salientes se encuentran:
678
679 Objetos *pesados*
680    Objetos polimórficos como los de cualquier lenguaje con orientación real
681    a objetos. Estos objetos poseen una tabla virtual para despacho dinámico,
682    todos los métodos son virtuales a menos que se indique lo contrario
683    y tienen semántica de referencia [#drefsem]_. Estos objetos tienen un
684    *overhead* comparados a los objetos *livianos* pero aseguran una semántica
685    segura para trabajar con orientación a objetos, evitando problemas con los
686    que se enfrenta C++ (como *slicing* [#dslicing]_) debido a que permite
687    semántica por valor [#dvalsem]_ [DWCL]_.
688
689    .. [#drefsem] Semántica de referencia significa que el tipo es tratado como
690       si fuera un puntero. Nunca se hacen copias del objeto, siempre se pasa
691       por referencia.
692    .. [#dslicing] Este problema se da en C++ cuando se pasa una clase derivada
693       a una función que acepta una clase base por valor como parámetro. Al
694       realizarse una copia de la clase con el constructor de copia de la clase
695       base, se pierden (o *rebanan*) los atributos de la clase derivada, y la
696       información de tipos en tiempo de ejecución (*RTTI*).
697    .. [#dvalsem] Semántica de valor significa que el tipo es tratado como si
698       fuera un valor concreto. En general se pasa por valor y se hacen copias
699       a menos que se utilice explícitamente un puntero.
700
701    D_ además soporta tipos de retorno covariantes para funciones virtuales.
702    Esto significa que una función sobreescrita por una clase derivada puede
703    retornar un tipo que sea derivado del tipo retornado por la función
704    original sobreescrita [DWFU]_.
705
706    Ejemplo::
707
708       class A { }
709       class B : A { }
710
711       class Foo {
712          A test() { return null; }
713       }
714
715       class Bar : Foo {
716          B test() { return null; } // sobreescribe y es covariante con Foo.test()
717       }
718
719 Interfaces
720    D_ no soporta herencia múltiple pero sí interfaces. Una interfaz es
721    básicamente una tabla virtual, una definición de métodos virtuales que debe
722    proveer una clase. Las interfaces no proveen una implementación de dichos
723    métodos, ni pueden tener atributos. Esto simplifica mucho el lenguaje y no
724    se pierde flexibilidad porque puede conseguirse el mismo efecto de tener
725    herencia múltiple a través de interfaces y *mixins* para proveer una
726    implementación o atributos en común a varias clases que implementan la
727    misma interfaz [DWIF]_.
728
729 Sobrecarga de operadores
730    La sobrecarga de operadores permite que un objeto tenga una sintaxis
731    similar a un tipo de dato nativo. Esto es muy importante además para la
732    programación genérica [DWOO]_.
733
734 Clases anidadas
735    Al igual que C (con respecto a ``struct``) y C++, pueden anidarse clases
736    dentro de clases. D_ sin embargo provee la posibilidad de acceder
737    a atributos de la instancia exterior desde la anidada [DWNC]_.
738
739    Ejemplo::
740
741       class Exterior {
742          int m;
743          class Anidada {
744             int foo() {
745                return m; // ok, puede acceder a un miembro de Exterior
746             }
747          }
748       }
749
750    Esto tiene un pequeño *overhead* ya que la clase ``Anidada`` debe guardar
751    un puntero a la clase ``Exterior``. Si no se necesita este comportamiento
752    es posible evitar este *overhead* utilizando ``static``, en cuyo caso solo
753    puede acceder a atributos estáticos de la clase ``Exterior``.
754
755    Ejemplo::
756
757       class Exterior {
758          int m;
759          static int n;
760          static class Anidada {
761             int foo() {
762                //return m; // error, miembro de Exterior
763                return n; // ok,   miembro estático de Exterior
764             }
765          }
766       }
767
768
769 Propiedades (*properties*)
770    En D_ se refiere a funciones miembro que pueden ser tratadas
771    sintácticamente como campos de esa clase/estructura [DWPR]_.
772
773    Ejemplo::
774
775       class Foo {
776          int data() { return _data; } // propiedad de lectura
777          int data(int value) { return _data = value; } // de escritura
778          private int _data;
779       }
780       Foo f = new Foo;
781       f.data = 1;       // llama a f.data(1)
782       int i = f.data; // llama a f.data()
783
784    Además tipos nativos, clases, estructuras y expresiones tienen
785    *properties* predefinidos, por ejemplo:
786
787    ``sizeof``
788       Tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4).
789
790    ``init``
791       Valor de inicialización por omisión (ejemplo: ``float.init`` -> *NaN*
792       [#dnan]_).
793
794    .. [#dnan] Del inglés *Not A Number*, es un valor especial codificado según
795       IEEE 754-2008 [IEEE754]_ que indica que estamos ante un valor inválido.
796
797    ``stringof``
798       Representación textual del símbolo o expresión (ejemplo:
799       ``(1+2).stringof`` -> ``"1 + 2"``).
800
801    ``mangleof``
802       Representación textual del tipo *mutilado* [#dmangle]_ [DWAB]_.
803
804    .. [#dmangle] *Name mangling* es el nombre dado comúnmente a una técnica
805       necesaria para poder sobrecargar nombres de símbolos. Consiste en
806       codificar los nombres de las funciones tomando como entrada el nombre de
807       la función y la cantidad y tipo de parámetros, asegurando que dos
808       funciones con el mismo nombre pero distintos parámetros (sobrecargada)
809       tengan nombres distintos.
810
811    ``alignof``
812       Alineación de una estructura o tipo.
813
814    Estos son solo los *properties* predefinidos para todos los tipos, pero hay
815    una cantidad considerable de *properties* extra para cada tipo.
816
817
818
819 .. _d_dbc:
820
821 Programación confiable
822 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
823
824 Programación confiable se refiere a las capacidades o facilidades que provee
825 el lenguaje para evitar fallas de manera temprana (o la capacidad de evitar
826 que ciertas fallas puedan existir directamente). D_ presta particular atención
827 a esto y provee las siguientes herramientas:
828
829 Excepciones
830    D_ soporta excepciones de manera similar a Java_: provee ``try``, ``catch``
831    y ``finally``. Esto permite que los errores difícilmente pasen
832    silenciosamente sin ser detectados [DWEX]_.
833
834 ``assert``
835    Es una condición que debe cumplirse siempre en un programa, como un chequeo
836    de integridad. Esto es muy utilizado en C/C++, donde ``assert()`` es una
837    *macro* que solo se compila cuando la *macro* ``NDEBUG`` no está definida.
838    Esto permite eliminar los chequeos de integridad del programa, que pueden
839    ser costosos, para versiones que se suponen estables.
840
841    D_ lleva este concepto más allá y hace al ``assert`` parte del lenguaje
842    [DWCP]_.  Si una verificación no se cumple, lanza una excepción. El
843    ``assert`` no es compilado cuando se utiliza una opción del compilador.
844
845    Ejemplo::
846
847       File f = open("archivo");
848       assert (f.ok());
849
850 Diseño por contrato
851    El diseño por contrato es un concepto introducido por el lenguaje Eiffel_
852    a mediados/finales de los '80. Se trata de incorporar en el lenguaje las
853    herramientas para poder aplicar verificaciones formales a las interfaces de
854    los programas.
855
856    D_ implementa las siguientes formas de diseño por contrato (todas se
857    ejecutan siempre y cuando no se compile en modo *release*, de manera de no
858    sacrificar rendimiento cuando es necesario) [DWCP]_:
859
860    Pre y post condiciones
861       Ejemplo::
862
863          double raiz_cuadrada(double x)
864          in { // pre-condiciones
865             assert (x >= 0.0);
866          }
867          out (resultado) { // post-condiciones
868             assert (resultado >= 0.0);
869             if (x < 1.0)
870                assert (resultado < x);
871             else if (x > 1.0)
872                assert (resultado > x);
873             else
874                assert (resultado == 1);
875          }
876          body {
877             // implementación
878          }
879
880    Invariantes de representación
881       La invariante de representación es un método de una clase o estructura
882       que es verificada cuando se completa su construcción, antes de la
883       destrucción, antes y después de ejecutar cualquier función miembro
884       pública y cuando se lo requiere de forma explícita utilizando
885       ``assert``.
886
887       Ejemplo::
888
889          class Fecha {
890                int dia;
891                int hora;
892                invariant() {
893                   assert(1 <= dia && dia <= 31);
894                   assert(0 <= hora && hora < 24);
895                }
896          }
897
898 Pruebas unitarias
899    Es posible incluir pequeñas pruebas unitarias en el lenguaje. Éstas son
900    ejecutadas (cuando no se compila en modo *release*) al comenzar el
901    programa, antes de que la función ``main()`` [DWUT]_.
902
903    Ejemplo::
904
905       unittest {
906          Fecha fecha;
907          fecha.dia = 5;
908          assert (fecha.dia == 5);
909          assert (fecha);
910       }
911
912 Orden de construcción estática
913    A diferencia de C++, D_ garantiza el orden de inicialización de los
914    módulos. Si bien en C++ no hay módulos si no unidades de compilación, es
915    posible que se ejecute código antes del ``main()`` en C++, si hay, por
916    ejemplo, instancias globales con un constructor definido. C++ no garantiza
917    un orden de inicialización, lo que trae muchos problemas. En D_ se define
918    el orden de inicialización y es el mismo orden en que el usuario importa
919    los módulos [DWMO]_.
920
921 Inicialización garantizada
922    Todas las variables son inicializadas por el lenguaje (a menos que el
923    usuario pida explícitamente que no lo sean) [DWTY]_ [DWVI]_. Siempre que
924    sea posible se elijen valores de inicialización que permitan saber al
925    programador que la variable no fue inicializada explícitamente, de manera
926    de poder detectar errores de manera temprana.
927
928    Ejemplo::
929
930       double d;      // inicializado a NaN
931       int x;         // inicializado a 0
932       Fecha f;       // inicializado a null
933       byte[5] a;     // inicializados todos los valores a 0
934       long l = void; // NO inicializado (explícitamente)
935
936 *RAII* (*Resource Adquisition Is Initialization*)
937    Es una técnica muy utilizada en C++ que consiste en reservar recursos por
938    medio de la construcción de un objeto y liberarlos cuando se libera éste.
939    Al llamarse al destructor de manera automática cuando se sale del *scope*,
940    se asegura que el recurso será liberado también.
941
942    Esta técnica es la base para desarrollar código seguro en cuanto
943    a excepciones (*exception-safe*) [SUTT99]_.
944
945    En D_ no es tan común utilizar *RAII* dada la existencia del recolector de
946    basura (en la mayoría de los casos el recurso a administrar es
947    sencillamente memoria). Sin embargo en los casos en donde es necesario,
948    puede utilizarse *RAII* mediante la utilización de la palabra reservada
949    ``scope``, que limita la vida de un objeto a un bloque de código [DWES]_.
950
951    Ejemplo::
952
953       class Archivo {
954          this() { /* adquiere recurso */ }
955          ~this() { /* libera recurso */ }
956       }
957       void f() {
958          scope Archivo archivo = new Archivo;
959          // uso de archivo
960       } // en este punto se llama al destructor de archivo
961
962 Guardias de bloque (*scope guards*)
963    Además de poder limitar la vida de una instancia a un *scope*, es posible
964    especificar un bloque de código arbitrario a ejecutar al abandonar un
965    *scope*, ya sea cuando se sale del *scope* normalmente o por una falla
966    [DWES]_.
967
968    Ejemplo::
969
970       int f(Lock lock) {
971          lock.lock();
972          scope (exit)
973             lock.unlock();              // ejecutado siempre que salga de f()
974          auto trans = new Transaccion;
975          scope (success)
976             trans.commit();             // ejecutado si sale con "return"
977          scope (failure)
978             trans.rollback();           // ejecutado si sale por una excepción
979          if (condicion)
980             throw Exception("error");   // lock.unlock() y trans.rollback()
981          else if (otra_condicion)
982             return 5;                   // lock.unlock() y trans.commit()
983          return 0;                      // lock.unlock() y trans.commit()
984       }
985
986    Esta es una nueva forma de poder escribir código *exception-safe*, aunque
987    el programador debe tener un poco más de cuidado de especificar las
988    acciones a ejecutar al finalizar el *scope*.
989
990 Primitivas de sincronización de hilos
991    La programación multi-hilo está directamente soportada por el lenguaje,
992    y se provee una primitiva de sincronización al igual que Java_. La palabra
993    reservada ``synchronized`` puede aparecer como modificador de métodos (en
994    cuyo caso se utiliza un *lock* por clase para sincronizar) o como una
995    sentencia, en cuyo caso se crea un *lock* global por cada bloque
996    ``synchronized`` a menos que se especifique sobre qué objeto realizar la
997    sincronización [DWSY]_. Por ejemplo::
998
999       class Foo {
1000          synchronized void bar() { /* cuerpo */ }
1001       }
1002
1003    Es equivalente a::
1004
1005       class Foo {
1006          void bar() {
1007             synchronized (this) { /* cuerpo */ }
1008          }
1009       }
1010
1011
1012 Compiladores
1013 ----------------------------------------------------------------------------
1014
1015 Hay, hasta el momento, 3 compiladores de D_ de buena calidad: DMD_, GDC_
1016 y LDC_.
1017
1018 DMD_ es el compilador de referencia, escrito por `Walter Bright`_. El
1019 *front-end* [#frontend]_ de este compilador ha sido liberado bajo licencia
1020 Artistic_/GPL_ y es utilizado por los otros dos compiladores, por lo tanto en
1021 realidad hay solo un compilador disponible con 3 *back-ends* [#backend]_
1022 diferentes.
1023
1024 .. [#frontend] *Front-end* es la parte del compilador encargada de hacer el
1025    análisis léxico, sintáctico y semántico del código fuente, generando una
1026    representación intermedia que luego el *back-end* convierte a código de
1027    máquina.
1028
1029 .. [#backend] El *back-end* es la parte del compilador encargada de convertir
1030    la representación intermedia generada por el *front-end* a código de
1031    máquina.
1032
1033 Con `DMD 1.041`__ se publicó el código fuente completo del compilador, pero
1034 con una licencia muy restrictiva para uso personal, por lo que el único efecto
1035 logrado por esto es que la gente pueda mandar parches o correcciones del
1036 compilador pero no lo convierte en `Software Libre`_, siendo el único de los
1037 3 compiladores que no tiene esta característica.
1038
1039 __ http://www.digitalmars.com/d/1.0/changelog.html#new1_041
1040
1041 El compilador GDC_ es el *front-end* de DMD_ utilizando al compilador GCC_
1042 como *back-end*. Fue un muy buen compilador pero estuvo abandonado por casi
1043 tres años. A mediados de este año recibió un nuevo impulso y de a poco se está
1044 poniendo al día con los *front-ends* actuales de DMD_ 1.0 y 2.0, aunque la
1045 versión 2.0 viene bastante más rezagada y todavía no es una alternativa viable
1046 a DMD_.
1047
1048 LDC_ sufrió una suerte similar, es un compilador joven que utiliza como
1049 *back-end* a LLVM_ (una infraestructura modera para construir compiladores),
1050 nacido a mediados de 2007 como un proyecto personal y privado de Tomas
1051 Lindquist Olsen, que estuvo trabajando de forma privada en el proyecto hasta
1052 mediados de 2008, momento en que decide publicar el código mediante una
1053 licencia libre.  Para ese entonces el compilador era todavía inestable
1054 y faltaban implementar varias cosas, pero el estado era lo suficientemente
1055 bueno como para captar varios colaboradores muy capaces, como `Christian
1056 Kamm`_ y Frits Van Bommel que rápidamente se convirtieron en parte fundamental
1057 del proyecto. El primer *release* (0.9) de una versión relativamente completa
1058 y estable fue a principios de 2009 que fue seguido por la versión 0.9.1 que
1059 como puntos más salientes agregó soporte para x86-64 y assembly embebido. El
1060 compilador tuvo un crecimiento excepcional pero estuvo muy inactivo por algún
1061 tiempo y, si bien sigue siendo mantenido, en general los nuevos *front-end* de
1062 DMD_ llevan tiempo de integrar y no está al día con el *back-end* de LLVM_
1063 (por ejemplo desde que se actualizó para utilizar LLVM_ 2.7 que perdió la
1064 capacidad de generar símbolos de depuración).
1065
1066 Además de estos compiladores hay varios otros experimentales, pero ninguno de
1067 ellos de calidad suficiente todavía. Por ejemplo hay un compilador
1068 experimental que emite *CIL* (*Common Intermediate Language*), el *bytecode*
1069 de `.NET`_, llamado DNet_. También hay un *front-end* escrito en D_, llamado
1070 Dil_.
1071
1072 Originalmente, dado que GDC_ estaba siendo mantenido y que LDC_ no existía,
1073 este trabajo iba a ser realizado utilizando GDC_ como compilador, dado que al
1074 ser `Software Libre`_ podía ser modificado de ser necesario. Pero finalmente,
1075 dada la poca confiabilidad que presenta la continuidad del desarrollo de tanto
1076 GDC_ como LDC_, y que el código de DMD_ está disponible en su totalidad
1077 (aunque no sea `Software Libre`_ por completo), se optó por utilizar este
1078 último, dado que es la implementación de referencia que fue más constantemente
1079 mantenida y desarrollada.
1080
1081
1082 .. include:: links.rst
1083
1084 .. vim: set ts=3 sts=3 sw=3 et tw=78 spelllang=es :