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