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