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