]> git.llucax.com Git - z.facultad/75.00/informe.git/blob - source/d.rst
a6af7c336fc1221cdcaf74e6a6365332979d48d2
[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: int)(T x, T y) { return x + y + 1; }
278          auto i = sumar(5, 6);         // i == 12
279          auto f = sumar(5.0f, 6.0f) // f == 11.0f
280
281       Ejemplo de especialización parcial::
282
283          T sumar(T: T*)(T x, T y) { return *x + *y; }
284          int x = 5, y = 6;
285          auto i = sumar(&x, &y); // i == 11
286          float v = 5.0f, w = 6.0f;
287          auto f = sumar(&v, &w); // f == 11.0f
288
289    Tipos, valores (incluyendo *strings*) y *templates* como parámetros
290       Este es otro bloque de construcción importantísimo para la programación
291       genérica en D, ya que combinando *templates* que toman *strings* como
292       parámetro en combinación con *string mixins* pueden hacerse toda clase
293       de meta-programas.
294
295       Ejemplo::
296
297          template hash(string s, uint so_far=0) {
298             static if (s.length == 0)
299                const hash = so_far;
300             else
301                const hash = hash!(s[1 .. length], so_far * 11 + s[0]);
302          }
303          string s = hash!("hola"); // calculado en tiempo de compilación
304
305    Cantidad de parámetros variables para *templates*
306       Esta característica permite implementar tuplas y otros algoritmos que
307       inherentemente deben tomar una cantidad variable de parámetros en tiempo
308       de compilación.
309
310       Ejemplo::
311
312          double sumar(T...)(T t) {
313             double res = 0.0;
314             foreach (x; t)
315                res += x;
316             return res;
317          }
318          double d = sumar(1, 2.0, 3.0f, 4l); // d == 10.0
319
320 *CTFE* (*compile-time function execution*)
321    Si una función cumple ciertas reglas básicas (como por ejemplo no tener
322    efectos colaterales) puede ser ejecutada en tiempo de compilación en vez de
323    tiempo de ejecución. Esto permite hacer algunos cálculos que no cambian de
324    ejecución en ejecución al momento de compilar, mejorando el rendimiento
325    o permitiendo formas avanzadas de meta-programación. Esta característica se
326    vuelve particularmente útil al combinarse con *string mixins* [DWCF]_.
327
328    Ejemplo::
329
330       int factorial(int n) {
331          if (n == 1)
332             return 1;
333          else
334             return n * factorial(n - 1);
335       }
336       static int x = factorial(5); // calculado en tiempo de compilación
337       int x = factorial(5); // calculado en tiempo de ejecución
338
339    Esta característica es muy importante para evitar la duplicación de código.
340
341 *Mixins*, incluyendo *string mixins*
342    La palabra *mixin* tiene significados distintos en varios lenguajes de
343    programación. En D_ *mixin* significa tomar una secuencia arbitraria de
344    declaraciones e insertarla en el contexto (*scope*) actual. Esto puede
345    realizarse a nivel global, en clases, estructuras o funciones. Esto sirve
346    como un mecanismo para evitar duplicación de código que puede ser
347    introducida por la falta de herencia múltiple [DWMT]_.
348
349    Ejemplo::
350
351       class A {
352          mixin bloque!(int, float);
353       }
354       A a = new A;
355       a.x = 5;
356       float f = a.foo(a.x);
357
358       class B {
359          mixin bloque!(long, double);
360       }
361       B b = new B;
362       b.x = 5l;
363       double d = a.foo(a.x);
364
365    *String mixin* se refiere a la capacidad de *incrustar* un *string* que
366    contenga un fragmento de código en un programa como si este fragmento
367    hubiera sido escrito en el código fuente directamente por el programador.
368    Esto permite hacer manipulaciones arbitrariamente complejas en combinación
369    con funciones ejecutadas en tiempo de compilación [DWME]_ [DWMX]_.
370
371    Ejemplo::
372
373       string generar_sumar(string var_x, string var_y) {
374          return "return " ~ var_x ~ " + " ~ var_y ~ ";";
375       }
376
377       int sumar(int a, int b) {
378          mixin(generar_sumar!("a", b"));
379       }
380
381 Expresiones ``is``
382    Las *expresiones ``is``* permiten la compilación condicional basada en las
383    características de un tipo [DWIE]_.
384
385    Ejemplo::
386
387       T foo(T)(T x) {
388          static if (is(T == class))
389             return new T;
390          else
391             return T.init;
392       }
393
394    Esto provee además una forma simple de reflexión en tiempo de compilación.
395
396
397
398 .. _d_low_level:
399
400 Programación de bajo nivel (*system programming*)
401 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
402
403 Por programación de bajo nivel nos referimos a la capacidad de un lenguaje de
404 manipular el hardware directamente, o al menos la memoria. C es probablemente
405 el lenguaje de bajo nivel más popular, seguido por C++.
406
407 D_ presenta muchas características de bajo nivel:
408
409 Compila a código de máquina nativo
410    Los programas generados por D_ no son interpretados ni necesitan una
411    máquina virtual como otros lenguajes de más alto nivel como Java_, `C#`_,
412    Python_, etc [DWOV]_.
413
414 *Assembly* empotrado
415    Provee acceso directo al *hardware* y la posibilidad de utilizar cualquier
416    característica de éste que no esté disponible en el lenguaje.
417
418    Una ventaja sobre C y C++ es que el lenguaje *assembly* utilizado dentro de
419    D_ está especificado, por lo que se puede mantener la portabilidad entre
420    compiladores incluso cuando se utiliza *assembly* (mientras que no se
421    cambie de arquitectura, por supuesto) [DWIA]_.
422
423 ``goto``
424    Al igual que C y C++, D_ provee la flexibilidad del uso de ``goto``
425    [DWGT]_.
426
427 Compatibilidad con C
428    Soporta todos los tipos de C y es ABI [#abi]_ compatible con éste. Esto
429    permite enlazar archivos objeto estándar de C y D_ en un mismo programa.
430    Además permite interoperar con C a través de ``extern (C)`` [DWCC]_.
431
432    .. [#abi] Interfaz de Aplicación Binaria (del inglés *Application Binary
433       Interface*).
434
435    Ejemplo::
436
437       extern (C) printf(const char* format, ...);
438       printf("3 + 5 == %d\n", 3 + 5); // llama al printf de C
439
440 Manejo de memoria explícito
441    Permite asignar estructuras en el *stack* o en el *heap*, haciendo uso de
442    los servicios del sistema operativo o la biblioteca estándar de C [DWMM]_.
443
444 Objetos y arreglos *livianos*
445    Por objetos *livianos* se entiende no-polimórficos. Es decir, un
446    agrupamiento de variables análogo al ``struct`` de C, sin tabla virtual ni
447    otro tipo de *overhead*. Los arreglos *livianos* son arreglos estáticos
448    como en C, cuyo tamaño es fijo, también sin ningún tipo de *overhead* como
449    C. Además puede asignarse un arreglo dinámicamente usando ``malloc()``
450    y utilizar el operador ``[]`` para accederlo [DWST]_ [DWCL]_.
451
452    Esto también permite interoperar con C, ya que pueden definirse ``structs``
453    y arreglos que pueden ser intercambiados con dicho lenguaje sin problemas.
454
455    Ejemplo::
456
457       struct timeval {
458          time_t         tv_sec;
459          suseconds_t tv_usec;
460       }
461       extern (C) {
462          void* malloc(size_t);
463          size_t strlen(const char *);
464          int gettimeofday(timeval *, void *);
465       }
466       char* s = cast(char*) malloc(2);
467       s[0] = 'C';
468       s[1] = '\0';
469       size_t l = strlen(s); // l == 1
470       timeval tv;
471       gettimeofday(&tv, null);
472
473 Rendimiento
474    La :ref:`d_generic` permite realizar muchas optimizaciones ya que se
475    resuelve en tiempo de compilación y por lo tanto aumenta el rendimiento en
476    la ejecución [DWTP]_.
477
478 Número de punto flotante de 80 bits
479    El tipo ``real`` de D_ tiene precisión de 80 bits si la plataforma lo
480    soporta (por ejemplo en i386) [DWTY]_.
481
482 Control de alineación de miembros de una estructura
483    Mediante ``align`` se puede especificar la alineación a tener en una
484    estructura [DWAL]_.
485
486    Ejemplo::
487
488       align (1)
489       struct paquete_de_red {
490          char   tipo;
491          short valor;
492       }
493       // paquete_de_red.sizeof == 3
494
495
496
497 .. _d_high_level:
498
499 Programación de alto nivel
500 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
501
502 Programación de alto nivel se refiere a construcciones más avanzadas que una
503 sentencia para iterar; expresiones con una semántica más ricas que proveen de
504 mayor expresividad al programador o le permiten focalizarse de mejora manera
505 en los algoritmos independizándose del *hardware* o de como funciona una
506 computadora. Es exactamente el opuesto a :ref:`d_low_level`.
507
508 En general estas características tienen como efecto secundario una mejora de la
509 productividad de los programadores. D_ adopta herramientas de muchos lenguajes
510 de alto nivel, como Java_ y Python_, por ejemplo:
511
512 Manejo automático de memoria
513    Al igual que C/C++ y prácticamente cualquier lenguaje imperativo maneja
514    automáticamente el *stack*, pero a diferencia de la mayoría de los
515    lenguajes de bajo nivel, D_ permite manejar el *heap* de manera automática
516    también a través de un *recolector de basura* [DWGC]_.
517
518 Sistema de paquetes y módulos (similar a Java_ o Python_)
519    Un módulo es una unidad que agrupa clases, funciones y cualquier otra
520    construcción de lenguaje. Un paquete es una agrupación de módulos. D_
521    asocia un módulo a un archivo fuente (y un archivo objeto cuando éste es
522    compilado) y un paquete a un directorio. A diferencia de C/C++ no necesita
523    de un preprocesador para incluir declaraciones de otros *módulos* (en C/C++
524    no existe el concepto de módulo, solo de unidades de compilación) [DWMO]_.
525
526    Ejemplo:
527
528    ``a.d``::
529
530       module a;
531       void f() {}
532
533    ``b.d``::
534
535       module b;
536       void f() {}
537
538    ``c.d``::
539
540          module c;
541          import a;
542          import b: f;
543          a.f();
544          b.f();
545          f(); // ejecuta b.f()
546
547 Funciones y delegados
548    Las funciones pueden ser sobrecargadas (funciones con el mismo nombre pero
549    distinta cantidad o tipo de parámetros), pueden especificarse argumentos de
550    entrada, salida o entrada/salida, argumentos por omisión o argumentos
551    evaluados de forma perezosa (*lazy*). Además pueden tener una cantidad de
552    argumentos variables pero manteniendo información de tipos (más seguro que
553    C/C++) [DWFU]_.
554
555    Los *delegados* son punteros a función con un contexto asociado. Este
556    contexto puede ser un objeto (en cuyo caso la función es un método) o un
557    *stack frame* (en cuyo caso la función es una función anidada).
558
559    Además de esto los delegados son ciudadanos de primera clase
560    [#1stclasscity]_, disponiendo de forma literal (delegado anónimo), lo que
561    permite construcciones de alto nivel muy conveniente. Los argumentos
562    evaluados de forma perezosa no son más que un delegado que se ejecuta solo
563    cuando es necesario.
564
565    .. [#1stclasscity] Por ciudadano de primera clase se entiende que se trata
566       de un tipo soportado por completo por el lenguaje, disponiendo de
567       expresiones literales anónimas, pudiendo ser almacenados en variables,
568       estructuras de datos, teniendo una identidad intrínseca, más allá de un
569       nombre dado, etc. En realidad los arreglos asociativos no pueden ser
570       expresados como literales anónimos pero sí tienen una sintaxis especial
571       soportada directamente por el lenguaje.
572
573    Ejemplo::
574
575       bool buscar(T[] arreglo, T item, bool delegate(T x, T y) igual) {
576          foreach (t, arreglo)
577             if (igual(t, item))
578                return true;
579          return false;
580       }
581       struct Persona {
582          string nombre;
583       }
584       Persona[] personas;
585       // llenas personas
586       Persona p;
587       p.nombre = "Carlos";
588       bool encontrado = buscar(personas, p,
589                                        (Persona x, Persona y) {
590                                           return x.nombre == y.nombre;
591                                        }
592                                  );
593
594 Arreglos *dinámicos* y arreglos asociativos
595    Los arreglos *dinámicos* son arreglos de longitud variable manejados
596    automáticamente por el lenguaje (análogos al ``std::vector`` de C++).
597    Soportan concatenación (a través del operador ``~``), rebanado o *slicing*
598    (a través del operador ``[x..y]``) y chequeo de límites (*bound checking*)
599    [DWAR]_.
600
601    Los arreglos asociativos (también conocidos como *hashes* o diccionarios)
602    también son provistos por el lenguaje [DWAA]_.
603
604    Ambos son ciudadanos de primera clase, disponiendo de forma literal.
605
606    Ejemplo::
607
608       int[] primos = [ 2, 3, 5, 7, 11, 13, 17, 19 ];
609       primos ~= [ 23, 29 ];
610       auto menores_que_10 = primos[0..4]; // [ 2, 3, 5, 7 ]
611       int[string] agenda;
612       agenda["Pepe"] = 5555_1234;
613
614 *Strings*
615    Al igual que los delegados y arreglos dinámicos y asociativos, los
616    *strings* son ciudadanos de primera clase, teniendo forma literal y siendo
617    codificados en UTF-8/16/32. Son un caso particular de arreglo dinámico y es
618    posible utilizarlos en sentencias ``switch``/``case`` [DWSR]_.
619
620    Ejemplo::
621
622       string s = "árbol";
623
624       switch (s) {
625          case "árbol":
626             s = "tree";
627          default:
628             s = "";
629       }
630
631 ``typedef`` y ``alias``
632    El primero define un nuevo tipo basado en otro. A diferencia de C/C++ el
633    tipo original no puede ser implícitamente convertido al tipo nuevo (excepto
634    valores literales), pero la conversión es válida en el otro sentido
635    (similar a los ``enum`` en C++). Por el contrario, ``alias`` es análogo al
636    ``typedef`` de C/C++ y simplemente es una forma de referirse al mismo tipo
637    con un nombre distinto [DWDC]_.
638
639    Ejemplo::
640
641       typedef int tipo;
642       int foo(tipo x) {}
643       tipo t = 10;
644       int i = 10;
645       foo(t);
646       foo(i); // error, no compila
647       alias tipo un_alias;
648       un_alias a = t;
649       foo(a);
650
651 Documentación embebida
652    D_ provee un sistema de documentación embebida, análogo a lo que proveen
653    Java_ o Python_ en menor medida. Hay comentarios especiales del código que
654    pueden ser utilizados para documentarlo de forma tal que luego el
655    compilador pueda extraer esa información para generar un documento [DWDO]_.
656
657 Números complejos
658    D_ soporta números complejos como ciudadanos de primera clase. Soporta
659    forma literal de números imaginarios y complejos [DWTY]_.
660
661    Ejemplo::
662
663       ifloat im = 5.0i;
664       float   re = 1.0;
665       cfloat c   = re + im; // c == 1.0 + 5.0i
666
667
668
669 Programación orientada a objetos
670 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
671
672 La orientación a objetos es probablemente el paradigma más utilizado en la
673 actualidad a la hora de diseñar e implementar un programa. D_ provee muchas
674 herramientas para soportar este paradigma de forma confiable. Entre las
675 características más salientes se encuentran:
676
677 Objetos *pesados*
678    Objetos polimórficos como los de cualquier lenguaje con orientación real
679    a objetos. Estos objetos poseen una tabla virtual para despacho dinámico,
680    todos los métodos son virtuales a menos que se indique lo contrario
681    y tienen semántica de referencia [#drefsem]_. Estos objetos tienen un
682    *overhead* comparados a los objetos *livianos* pero aseguran una semántica
683    segura para trabajar con orientación a objetos, evitando problemas con los
684    que se enfrenta C++ (como *slicing* [#dslicing]_) debido a que permite
685    semántica por valor [#dvalsem]_ [DWCL]_.
686
687    .. [#drefsem] Semántica de referencia significa que el tipo es tratado como
688       si fuera un puntero. Nunca se hacen copias del objeto, siempre se pasa
689       por referencia.
690    .. [#dslicing] Este problema se da en C++ cuando se pasa una clase derivada
691       a una función que acepta una clase base por valor como parámetro. Al
692       realizarse una copia de la clase con el constructor de copia de la clase
693       base, se pierden (o *rebanan*) los atributos de la clase derivada, y la
694       información de tipos en tiempo de ejecución (*RTTI*).
695    .. [#dvalsem] Semántica de valor significa que el tipo es tratado como si
696       fuera un valor concreto. En general se pasa por valor y se hacen copias
697       a menos que se utilice explícitamente un puntero.
698
699    D_ además soporta tipos de retorno covariantes para funciones virtuales.
700    Esto significa que una función sobreescrita por una clase derivada puede
701    retornar un tipo que sea derivado del tipo retornado por la función
702    original sobreescrita [DWFU]_.
703
704    Ejemplo::
705
706       class A { }
707       class B : A { }
708
709       class Foo {
710          A test() { return null; }
711       }
712
713       class Bar : Foo {
714          B test() { return null; } // sobreescribe y es covariante con Foo.test()
715       }
716
717 Interfaces
718    D_ no soporta herencia múltiple pero sí interfaces. Una interfaz es
719    básicamente una tabla virtual, una definición de métodos virtuales que debe
720    proveer una clase. Las interfaces no proveen una implementación de dichos
721    métodos, ni pueden tener atributos. Esto simplifica mucho el lenguaje y no
722    se pierde flexibilidad porque puede conseguirse el mismo efecto de tener
723    herencia múltiple a través de interfaces y *mixins* para proveer una
724    implementación o atributos en común a varias clases que implementan la
725    misma interfaz [DWIF]_.
726
727 Sobrecarga de operadores
728    La sobrecarga de operadores permite que un objeto tenga una sintaxis
729    similar a un tipo de dato nativo. Esto es muy importante además para la
730    programación genérica [DWOO]_.
731
732 Clases anidadas
733    Al igual que C (con respecto a ``struct``) y C++, pueden anidarse clases
734    dentro de clases. D_ sin embargo provee la posibilidad de acceder
735    a atributos de la instancia exterior desde la anidada [DWNC]_.
736
737    Ejemplo::
738
739       class Exterior {
740          int m;
741          class Anidada {
742             int foo() {
743                return m; // ok, puede acceder a un miembro de Exterior
744             }
745          }
746       }
747
748    Esto tiene un pequeño *overhead* ya que la clase ``Anidada`` debe guardar
749    un puntero a la clase ``Exterior``. Si no se necesita este comportamiento
750    es posible evitar este *overhead* utilizando ``static``, en cuyo caso solo
751    puede acceder a atributos estáticos de la clase ``Exterior``.
752
753    Ejemplo::
754
755       class Exterior {
756          int m;
757          static int n;
758          static class Anidada {
759             int foo() {
760                //return m; // error, miembro de Exterior
761                return n; // ok,   miembro estático de Exterior
762             }
763          }
764       }
765
766
767 Propiedades (*properties*)
768    En D_ se refiere a funciones miembro que pueden ser tratadas
769    sintácticamente como campos de esa clase/estructura [DWPR]_.
770
771    Ejemplo::
772
773       class Foo {
774          int data() { return _data; } // propiedad de lectura
775          int data(int value) { return _data = value; } // de escritura
776          private int _data;
777       }
778       Foo f = new Foo;
779       f.data = 1;       // llama a f.data(1)
780       int i = f.data; // llama a f.data()
781
782    Además tipos nativos, clases, estructuras y expresiones tienen
783    *properties* predefinidos, por ejemplo:
784
785    ``sizeof``
786       Tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4).
787
788    ``init``
789       Valor de inicialización por omisión (ejemplo: ``float.init`` -> *NaN*
790       [#dnan]_).
791
792    .. [#dnan] Del inglés *Not A Number*, es un valor especial que indica que
793       estamos ante un valor inválido.
794
795    ``stringof``
796       Representación textual del símbolo o expresión (ejemplo:
797       ``(1+2).stringof`` -> ``"1 + 2"``).
798
799    ``mangleof``
800       Representación textual del tipo *mutilado* [#dmangle]_.
801
802    .. [#dmangle] *Name mangling* es el nombre dado comunmente a una técnica
803       necesaria para poder sobrecargar nombres de símbolos. Consiste en
804       codificar los nombres de las funciones tomando como entrada el nombre de
805       la función y la cantidad y tipo de parámetros, asegurando que dos
806       funciones con el mismo nombre pero distintos parámetros (sobrecargada)
807       tengan nombres distintos.
808
809    ``alignof``
810       Alineación de una estructura o tipo.
811
812    Estos son solo los *properties* predefinidos para todos los tipos, pero hay
813    una cantidad considerable de *properties* extra para cada tipo.
814
815    Más información sobre *properties* de clases en
816    http://www.digitalmars.com/d/1.0/property.html#classproperties y sobre
817    *properties* predefinidos en
818    http://www.digitalmars.com/d/1.0/property.html
819
820
821
822 .. _d_dbc:
823
824 Programación confiable
825 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
826
827 Programación confiable se refiere a las capacidades o facilidades que provee
828 el lenguaje para evitar fallas de manera temprana (o la capacidad de evitar
829 que ciertas fallas puedan existir directamente). D_ presta particular atención
830 a esto y provee las siguientes herramientas:
831
832 Excepciones
833    D_ soporta excepciones de manera similar a Java_: provee ``try``, ``catch``
834    y ``finally``. Esto permite que los errores difícilmente pasen
835    silenciosamente sin ser detectados [DWEX]_.
836
837 ``assert``
838    Es una condición que debe cumplirse siempre en un programa, como un chequeo
839    de integridad. Esto es muy utilizado en C/C++, donde ``assert()`` es una
840    *macro* que solo se compila cuando la *macro* ``NDEBUG`` no está definida.
841    Esto permite eliminar los chequeos de integridad del programa, que pueden
842    ser costosos, para versiones que se suponen estables.
843
844    D_ lleva este concepto más allá y hace al ``assert`` parte del lenguaje
845    [DWCP]_.  Si una verificación no se cumple, lanza una excepción. El
846    ``assert`` no es compilado cuando se utiliza una opción del compilador.
847
848    Ejemplo::
849
850       File f = open("archivo");
851       assert (f.ok());
852
853 Diseño por contrato
854    El diseño por contrato es un concepto introducido por el lenguaje Eiffel_
855    a mediados/finales de los '80. Se trata de incorporar en el lenguaje las
856    herramientas para poder aplicar verificaciones formales a las interfaces de
857    los programas.
858
859    D_ implementa las siguientes formas de diseño por contrato (todas se
860    ejecutan siempre y cuando no se compile en modo *release*, de manera de no
861    sacrificar rendimiento cuando es necesario) [DWCP]_:
862
863    Pre y post condiciones
864       Ejemplo::
865
866          double raiz_cuadrada(double x)
867          in { // pre-condiciones
868             assert (x >= 0.0);
869          }
870          out (resultado) { // post-condiciones
871             assert (resultado >= 0.0);
872             if (x < 1.0)
873                assert (resultado < x);
874             else if (x > 1.0)
875                assert (resultado > x);
876             else
877                assert (resultado == 1);
878          }
879          body {
880             // implementación
881          }
882
883    Invariantes de representación
884       La invariante de representación es un método de una clase o estructura
885       que es verificada cuando se completa su construcción, antes de la
886       destrucción, antes y después de ejecutar cualquier función miembro
887       pública y cuando se lo requiere de forma explícita utilizando
888       ``assert``.
889
890       Ejemplo::
891
892          class Fecha {
893                int dia;
894                int hora;
895                invariant() {
896                   assert(1 <= dia && dia <= 31);
897                   assert(0 <= hora && hora < 24);
898                }
899          }
900
901 Pruebas unitarias
902    Es posible incluir pequeñas pruebas unitarias en el lenguaje. Éstas son
903    ejecutadas (cuando no se compila en modo *release*) al comenzar el
904    programa, antes de que la función ``main()`` [DWUT]_.
905
906    Ejemplo::
907
908       unittest {
909          Fecha fecha;
910          fecha.dia = 5;
911          assert (fecha.dia == 5);
912          assert (fecha);
913       }
914
915 Orden de construcción estática
916    A diferencia de C++, D_ garantiza el orden de inicialización de los
917    módulos. Si bien en C++ no hay módulos si no unidades de compilación, es
918    posible que se ejecute código antes del ``main()`` en C++, si hay, por
919    ejemplo, instancias globales con un constructor definido. C++ no garantiza
920    un orden de inicialización, lo que trae muchos problemas. En D_ se define
921    el orden de inicialización y es el mismo orden en que el usuario importa
922    los módulos [DWMO]_.
923
924 Inicialización garantizada
925    Todas las variables son inicializadas por el lenguaje (a menos que el
926    usuario pida explícitamente que no lo sean) [DWTY]_ [DWVI]_. Siempre que
927    sea posible se elijen valores de inicialización que permitan saber al
928    programador que la variable no fue inicializada explícitamente, de manera
929    de poder detectar errores de manera temprana.
930
931    Ejemplo::
932
933       double d;      // inicializado a NaN
934       int x;         // inicializado a 0
935       Fecha f;       // inicializado a null
936       byte[5] a;     // inicializados todos los valores a 0
937       long l = void; // NO inicializado (explícitamente)
938
939 *RAII* (*Resource Adquisition Is Initialization*)
940    Es una técnica muy utilizada en C++ que consiste en reservar recursos por
941    medio de la construcción de un objeto y liberarlos cuando se libera éste.
942    Al llamarse al destructor de manera automática cuando se sale del *scope*,
943    se asegura que el recurso será liberado también.
944
945    Esta técnica es la base para desarrollar código seguro en cuanto
946    a excepciones (*exception-safe*) [SUTT99]_.
947
948    En D_ no es tan común utilizar *RAII* dada la existencia del recolector de
949    basura (en la mayoría de los casos el recurso a administrar es
950    sencillamente memoria). Sin embargo en los casos en donde es necesario,
951    puede utilizarse *RAII* mediante la utilización de la palabra reservada
952    ``scope``, que limita la vida de un objeto un bloque de código [DWES]_.
953
954    Ejemplo::
955
956       class Archivo {
957          this() { /* adquiere recurso */ }
958          ~this() { /* libera recurso */ }
959       }
960       void f() {
961          scope Archivo archivo = new Archivo;
962          // uso de archivo
963       } // en este punto se llama al destructor de archivo
964
965 Guardias de bloque (*scope guards*)
966    Además de poder limitar la vida de una instancia a un *scope*, es posible
967    especificar un bloque de código arbitrario a ejecutar al abandonar un
968    *scope*, ya sea cuando se sale del *scope* normalmente o por una falla
969    [DWES]_.
970
971    Ejemplo::
972
973       int f(Lock lock) {
974          lock.lock();
975          scope (exit)
976             lock.unlock();              // ejecutado siempre que salga de f()
977          auto trans = new Transaccion;
978          scope (success)
979             trans.commit();             // ejecutado si sale con "return"
980          scope (failure)
981             trans.rollback();           // ejecutado si sale por una excepción
982          if (condicion)
983             throw Exception("error");   // lock.unlock() y trans.rollback()
984          else if (otra_condicion)
985             return 5;                   // lock.unlock() y trans.commit()
986          return 0;                      // lock.unlock() y trans.commit()
987       }
988
989    Esta es una nueva forma de poder escribir código *exception-safe*, aunque
990    el programador debe tener un poco más de cuidado de especificar las
991    acciones a ejecutar al finalizar el *scope*.
992
993 Primitivas de sincronización de hilos
994    La programación multi-hilo está directamente soportada por el lenguaje,
995    y se provee una primitiva de sincronización al igual que Java_. La palabra
996    reservada ``synchronized`` puede aparecer como modificador de métodos (en
997    cuyo caso se utiliza un *lock* por clase para sincronizar) o como una
998    sentencia, en cuyo caso se crea un *lock* global por cada bloque
999    ``synchronized`` a menos que se especifique sobre qué objeto realizar la
1000    sincronización [DWSY]_. Por ejemplo::
1001
1002       class Foo {
1003          synchronized void bar() { /* cuerpo */ }
1004       }
1005
1006    Es equivalente a::
1007
1008       class Foo {
1009          void bar() {
1010             synchronized (this) { /* cuerpo */ }
1011          }
1012       }
1013
1014
1015 Compiladores
1016 ----------------------------------------------------------------------------
1017
1018 Hay, hasta el momento, 3 compiladores de D_ de buena calidad: DMD_, GDC_
1019 y LDC_.
1020
1021 DMD_ es el compilador de referencia, escrito por `Walter Bright`_. El
1022 *front-end* [#frontend]_ de este compilador ha sido liberado bajo licencia
1023 Artistic_/GPL_ y es utilizado por los otros dos compiladores, por lo tanto en
1024 realidad hay solo un compilador disponible con 3 *back-ends* [#backend]_
1025 diferentes.
1026
1027 .. [#frontend] *Front-end* es la parte del compilador encargada de hacer el
1028    análisis léxico, sintáctico y semántico del código fuente, generando una
1029    representación intermedia que luego el *back-end* convierte a código de
1030    máquina.
1031
1032 .. [#backend] El *back-end* es la parte del compilador encargada de convertir
1033    la representación intermedia generada por el *front-end* a código de
1034    máquina.
1035
1036 Con `DMD 1.041`__ se publicó el código fuente completo del compilador, pero
1037 con una licencia muy restrictiva para uso personal, por lo que el único efecto
1038 logrado por esto es que la gente pueda mandar parches o correcciones del
1039 compilador pero no lo convierte en `Software Libre`_, siendo el único de los
1040 3 compiladores que no tiene esta característica.
1041
1042 __ http://www.digitalmars.com/d/1.0/changelog.html#new1_041
1043
1044 El compilador GDC_ es el *front-end* de DMD_ utilizando al compilador GCC_
1045 como *back-end*. Fue un muy buen compilador pero estuvo abandonado por casi
1046 tres años. A mediados de este año recibió un nuevo impulso y de a poco se está
1047 poniendo al día con los *front-ends* actuales de DMD_ 1.0 y 2.0, aunque la
1048 versión 2.0 viene bastante más rezagada y todavía no es una alternativa viable
1049 a DMD_.
1050
1051 LDC_ sufrió una suerte similar, es un compilador joven que utiliza como
1052 *back-end* a LLVM_ (una infraestructura modera para construir compiladores),
1053 nacido a mediados de 2007 como un proyecto personal y privado de Tomas
1054 Lindquist Olsen, que estuvo trabajando de forma privada en el proyecto hasta
1055 mediados de 2008, momento en que decide publicar el código mediante una
1056 licencia libre.  Para ese entonces el compilador era todavía inestable
1057 y faltaban implementar varias cosas, pero el estado era lo suficientemente
1058 bueno como para captar varios colaboradores muy capaces, como `Christian
1059 Kamm`_ y Frits Van Bommel que rápidamente se convirtieron en parte fundamental
1060 del proyecto. El primer *release* (0.9) de una versión relativamente completa
1061 y estable fue a principios de 2009 que fue seguido por la versión 0.9.1 que
1062 como puntos más salientes agregó soporte para x86-64 y assembly embebido. El
1063 compilador tuvo un crecimiento excepcional pero estuvo muy inactivo por algún
1064 tiempo y, si bien sigue siendo mantenido, en general los nuevos *front-end* de
1065 DMD_ llevan tiempo de integrar y no está al día con el *back-end* de LLVM_
1066 (por ejemplo desde que se actualizó para utilizar LLVM_ 2.7 que perdió la
1067 capacidad de generar símbolos de depuración).
1068
1069 Además de estos compiladores hay varios otros experimentales, pero ninguno de
1070 ellos de calidad suficiente todavía. Por ejemplo hay un compilador
1071 experimental que emite *CIL* (*Common Intermediate Language*), el *bytecode*
1072 de `.NET`_, llamado DNet_. También hay un *front-end* escrito en D_, llamado
1073 Dil_.
1074
1075 Originalmente, dado que GDC_ estaba siendo mantenido y que LDC_ no existía,
1076 este trabajo iba a ser realizado utilizando GDC_ como compilador, dado que al
1077 ser `Software Libre`_ podía ser modificado de ser necesario. Pero finalmente,
1078 dada la poca confiabilidad que presenta la continuidad del desarrollo de tanto
1079 GDC_ como LDC_, y que el código de DMD_ está disponible en su totalidad
1080 (aunque no sea `Software Libre`_ por completo), se optó por utilizar este
1081 último, dado que es la implementación de referencia que fue más constantemente
1082 mantenida y desarrollada.
1083
1084
1085 .. include:: links.rst
1086
1087 .. vim: set ts=3 sts=3 sw=3 et tw=78 spelllang=es :