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