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