1 #LyX 1.3 created this file. For more info see http://www.lyx.org/
11 \paperpackage widemarginsa4
15 \use_numerical_citations 0
16 \paperorientation portrait
19 \paragraph_separation indent
21 \quotes_language english
25 \paperpagestyle default
34 Leandro Lucarella (77891)
41 \begin_inset LatexCommand \tableofcontents{}
51 El lenguaje de programación D fue concebido en el año 1999 como una re-ingenierí
52 a de C y C++ y siguen en la actualidad sin estar completamente definido
53 y con algunas cosas sin implementar.
54 Este lenguaje es compilado y de alto rendimiento pero con un nivel un poco
55 más alto que C o C++ (pero sin sacrificar la posibilidad de hacer cosas
56 de bajo nivel y muy eficientes).
57 D es compatible binariamente con C, pero
64 Uno de los principales objetivos de D es ser un lenguaje de programación
65 multi-paradigma, poniendo mucho énfasis en la practicidad (no pretende
66 ser un lenguaje académico estrictamente atado a un paradigma en particular).
67 También pone mucho énfasis en la programación segura (a pesar de dejar
68 bajar a un nivel muy bajo, al punto de poder embeber assembly, tiene muchas
69 herramientas para detectar y evitar errores).
73 \begin_inset LatexCommand \label{sub:Objetivo-del-lenguaje}
80 D, oficialmente, tiene los siguientes objetivos:
83 Reducir el costo de desarrollo en al menos un 10% agregando características
84 que mejoren la productividad y ajustando las características del lenguaje
85 para que los errores más comunes que más cuestan reparar sean evitados
89 Hacer más fácil escribir programas portables entre compiladores, arquitecturas
90 y sistemas operativos.
93 Soportar programación multi-paradigma; es decir, como mínimo, soportar los
94 paradigmas: imperativo, estructurado, orientado a objetos y programación
98 Tener una curva de aprendizaje corta para programadores que se sienten a
102 Proveer acceso irrestricto de bajo nivel cuando sea necesario.
105 Hacer que implementar un compilador sea mucho más sencillo que para C++.
108 Ser compatible con la ABI
114 Application Binary Interface, i.e.
115 mantener compatibilidad a nivel de código objeto con C.
121 Tener gramática libre de contexto.
124 Escribir fácilmente aplicaciones internacionalizadas.
127 Incorporar Programación por Contrato y metodologías de casos de prueba.
130 Ser capaz de construir programas independientes y livianos.
139 D tiene una gran variedad de tipos básicos, ya que, además de poseer todos
140 los tipos básicos para poder desarrollar a bajo nivel como en C, dispone
141 de números complejos y otros tipos no tan comunes.
144 Entre los tipos compatibles con C se encuentra:
154 char wchar byte short int long
160 char wchar ubyte ushort uint ulong
177 no tienen su contraparte signada, ya que son para uso explícito de variables
178 de caracter (UTF-8 y UTF-16 respectivamente).
179 Además agrega algunos nuevos tipos:
195 (128 bits, reservado para uso futuro);
199 (tipo de punto flotante más grande representable por la arquitectura, en
200 Intel es de 80 bits) y
207 Finalmente agrega el tipo básico imaginario, cuyos tipos son iguales que
212 (de punto flotante) pero anteponiendo una
225 con imaginarios se pueden forma complejos, cuyos variaciones son de la
226 misma forma, sólo que se antepone una
242 \begin_inset LatexCommand \label{sub:Tipos-derivados}
249 De los tipos básicos pueden derivarse otros tipos.
250 Esto tipos son punteros, array (estáticos, dinámicos y asociativos) y funciones
251 , siendo estas últimas tal vez un caso muy particular.
252 Los array tal vez podrían considerarse tipos compuestos, pero como la variable
253 en sí es un puntero, en realidad no lo es.
254 Es decir, para obtener un elemento del array hay que aplicar aritmética
263 utilizando el operador corchetes.
267 \begin_inset Quotes eld
271 \begin_inset Quotes erd
274 ; // Array dinámico de caracteres
278 \begin_inset Quotes eld
282 \begin_inset Quotes erd
285 ; // Se autoredimensiona
288 int[2] arr; // Array (estático) de 2 int
291 int[char[]] hash; // Array asociativo de int cuya clave es un char[]
294 void function() fp; // Puntero a una función void (void)
297 int function(bit) fp2; // Puntero a una función int (bit)
300 int delegate(bit) del; // Delegado de tipo int (bit)
303 Los delegados son algo así como punteros a función con contexto.
304 El contexto puede ser tanto un objeto como un
308 (el puntero al stack en donde se encuentra el padre lexicográfico de una
310 Veremos un poco más los delegados en la sección
311 \begin_inset LatexCommand \vref{sub:Operaciones}
316 \begin_inset LatexCommand \vref{sub:Rutinas}
326 D dispone de varias formas de definir tipos de usuario, entre ellos varios
329 \layout Subsubsection
334 Un alias es la forma más primitiva de tipo de usuario, simplemente es otra
335 forma de escribir un tipo ya definido (es análogo al typedef de C).
345 tipo t = i; // Correcto (semánticamente son los dos int)
348 A partir de ahora puedo hacer referencia a
357 Es decir, son semánticamente idénticos.
358 \layout Subsubsection
363 typedef es similar al alias, con la salvedad de que define un tipo semánticament
364 e distinto (por más que la estructura en memoria y la forma de manejarlo
366 Como consecuencia de esto, se efectúa chequeo de tipos y, por ejemplo,
367 no puedo asignar a una variable de un tipo que es un typedef de otro:
376 // No compila porque se está asignando un int a un tipo
382 tipo t = cast(tipo)(i); // Correcto (conversión explícita)
383 \layout Subsubsection
388 Enum es en realidad un
392 que puede tener sólo un número predefinido de valores, que además son represent
396 enum Dias { DOMINGO, LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO }
399 Dias d = Dias.MARTES;
400 \layout Subsubsection
405 Union es otro tipo de dato definido por el usuario proveniente de C, que
406 permite ver una misma
410 de memoria de distintas formas.
445 se guarda en la misma celda de memoria, por lo que se utilizan como mecanismos
446 alternativos para operar en ella, usando semántica de uno u otro tipo.
447 Esto es particularmente útil para aplicaciones de bajo nivel, donde el
448 espacio en memoria es muy reducido.
449 Esta técnica permite tener una variable cuyo tipo es, en cierto modo, variable.
450 \layout Subsubsection
455 El struct es muy similar al de C, con algunos agregados, como la posibilidad
456 de tener funciones miembro, inicializadores, etc.
457 No es más que el agrupamiento de un conjunto de variables, a las que se
458 accede a través de un identificador:
482 printf("dia: %d, mes: %d, anio: %d
503 \layout Subsubsection
506 \begin_inset LatexCommand \label{sub:tipo-class}
513 Las clases son la forma en la que D implementa la orientación a objetos,
514 que veremos en detalle más adelante.
515 Por ahora sólo adelantaremos que es muy similar a un struct, sólo que guarda
516 algo más de información de control (como la tabla virtual) para poder implement
517 ar polimorfismo y herencia.
518 \layout Subsubsection
523 Las interfaces son un caso particular de clases, que no puede tener atributos,
525 Una clase puede implementar varias interfaces, por lo que esto no e es
526 más que una forma limitada de implementar herencia múltiple, eliminando
527 el problema de la representación en memoria de los datos.
534 \begin_inset LatexCommand \label{sub:Operaciones}
541 D provee las operaciones básicas que provee prácticamente cualquier lenguaje:
542 asignación, comparación, incremento, decremento, suma, resta, multiplicación,
543 división, resto, álgebra booleana (and, or, xor, not), shifting.
546 int i = 1 << 1; // 0001b << 1 == 0010b == 2
549 int j = i >> 1; // 2 >> 1 == 0010b >> 1 == 0001b == 1
552 i -= j; // i = i - j = 2 - 1 = 1
558 i *= 4; // i = i * 4 = -1 * 4 = -4
561 i >>>= 1; // i = i >>> 1 = 1100b >>> 1 = 1110b = -2
564 i++; // i = i + 1 = -2 + 1 = -1
567 i |= j; // i = i | j = 1111b | 0001b = 1111b = -1
570 i &= j; // i = i & j = 1111b & 0001b = 0001b = 1
573 bit c = i > j; // c = 1 > 1 = false
576 c = i && j; // c = 1 && 1 = true
579 i = 3 / 2; // i = 3 / 2 = 1 (entero)
582 i = 3 % 2; // i = resto(3/2) = 1
585 También provee llamadas a funciones y delegados.
589 \begin_inset Quotes eld
595 \begin_inset Quotes erd
598 ); // Llama a void printf(char*, ...)
601 bit ok = esta_ok(10, 1.5); // Llama a bit esta_ok(int, float)
604 int n = objeto.cantidad(); // Llama a int Clase::cantidad(Clase)
607 int delegate(void) delegado;
610 delegado = &objeto.cantidad;
613 n = delegado(); // Llama a objeto.cantidad()
616 Además de esto, provee operaciones propias de un lenguaje imperativo de
617 bajo nivel: aritmética de punteros, operador [] como método alternativo
618 para acceder a una posición de un array, desreferenciamiento, obtención
619 de una dirección de memoria de una variable, etc.
625 arr[1] = 1; // asigno el segundo elemento (empieza en 0)
628 int* p = cast(int*) arr + 1; // apunto a arr[1]
631 *p = 2; // arr[1] = 2
634 *(--p) = 1; // p apunta a arr[0] y arr[0] = 1
637 p = &(arr[1]); // p apunta a arr[1]
640 También incluye un operador para comparar si 2 referencias referencian al
644 class C { int i = 0; int opEquals(C o) { return i == o.i; } }
668 y algunas operaciones propias de los arrays y hashes (array asociativos),
669 como para saber si existe una clave o concatenación y slicing de arrays.
684 arr3 = arr ~ arr2; // arr3 = (0,10,0,0,1)
693 1.0 in hash; // false
699 Finalmente provee un operador de resolución de scope, para acceder a variables
700 definidas dentro de tipos compuestos (como estructuras o uniones) o módulos.
704 \begin_inset LatexCommand \label{sub:Variables}
711 El lenguaje provee variables sin nombre a través de punteros y alocación
713 En general las instancias de clases son referencias (no puede ser alocadas
714 en el stack, en principio), por lo que podría decirse que toda instancia
715 de clase es una variable sin nombre.
716 Para alocar memoria se puede usar el operador
724 por el recolector de basura, o a través de la llamada al malloc de C (en
729 en D), que aloca memoria no
734 El manejo de referencias es automático, no hay forma de declarar una variable
736 Si la variable es de tipo clase, será una referencia, si no no (con algunas
737 excepciones, como al pasarse por parámetro).
738 Si se desean usar variables sin nombre que no sean clases, hay que usar
745 int* p = cast(int*) malloc(4 * int.sizeof); // Nunca serán recolectados
751 free(p); // Lo libero yo
754 Representación de la memoria
757 La representación en memoria es muy similar a cualquier lenguaje imperativo
758 compilado, como C o C++.
759 Cada tipo de variable ocupa una cierta cantidad de bytes y se almacenan
760 en memoria de forma contigua (al menos lógicamente), según la alineación
761 de la arquitectura para la que fue compilado.
762 Esto trae el clásico problema de los
766 que pueden quedar, para que cada variable ocupe un múltiplo de palabras
767 de la arquitectura, para manejarla con mayor eficiencia, por lo que el
768 compilador provee formas de especificar la alineación a usar.
771 Las variables globales (que incluye a las estáticas) se almacenan en tiempo
772 de compilación (estáticamente) dentro del código del programa, en el área
774 Las variables locales a las funciones se almacenan en una pila de ejecución,
775 por lo tanto debe tener una pila por cada hilo de ejecución.
776 Por último hay un área de memoria
780 que se le pide al sistema operativo a medida que se necesita (heap).
781 Una particularidad extra de D es que los tipos definidos por el usuario
786 , se almacenan en el heap.
787 En el stack y en el área de datos del programa sólo pueden guardarse referencia
788 s (punteros) a instancias de una clase (en realidad hay excepciones, ya
789 que se puede pedir memoria del stack
793 e inicializar el objeto en esa memoria, pero no es el caso general).
796 Como dijimos, los tipos simples ocupan una cantidad de memoria fija cada
798 Cada tipo derivado tiene sus propias particularidades.
799 \layout Subsubsection
804 El array estático no es más que una región contigua de bytes de tamaño N*S,
805 siendo N la cantidad de elementos y S el tamaño que ocupa el elemento.
806 Una variable de este tipo, entonces, no es más que un puntero al primer
808 \layout Subsubsection
813 Los array dinámicos, como su nombre lo indica, no tienen un tamaño fijo,
814 por lo tanto se guarda el tamaño además de los elementos en sí.
815 Una variable de este tipo es entonces un indicador de la cantidad actual
816 de elementos y un puntero al primer elemento.
817 Es por esto que típicamente este tipo de array ocupa 8 bytes (4 bytes para
818 almacenar N y 4 bytes para almacenar el puntero al primer elemento, que
819 se establecen en tiempo de ejecución) más los N*S para los elementos en
821 \layout Subsubsection
823 array asociativo (o hash)
826 La representación de este tipo de array no está aún definida, aunque al
827 igual que los array dinámico dice que la referencia ocupa 8 bytes, pero
828 no indica para que sirve cada byte, aunque es esperable que sea igual,
829 4 bytes para la cantidad de memoria alocada para la tabla de hash y 4 para
830 el puntero a la tabla en sí.
831 \layout Subsubsection
836 No es más que un int con un rango de valores posibles predefinidos y con
837 nombres simbólicos, por lo que simplemente se almacena como un int y todos
838 los chequeos se realizan en tiempo de compilación.
839 \layout Subsubsection
844 Las uniones ocupan en memoria, como mínimo, la misma la cantidad de bytes
845 que ocupa su elemento de mayor tamaño.
846 Como el tipo que se está usando para acceder se sabe en tiempo de compilación,
847 no es necesario almacenar datos extra, pero podría ocupar más lugar si
848 el compilador hiciera alguna optimización (para que ocupe múltiplos de
849 una palabra, por ejemplo).
850 \layout Subsubsection
855 Las estructuras, al igual que en C, se almacenan de forma continua ocupando,
857 \begin_inset Formula $\sum S_{i}$
861 \begin_inset Formula $S_{i}$
864 el tamaño del elemento i del struct.
865 Nuevamente, los tamaños se conocen en tiempo de compilación por lo que
866 no es necesario guardar datos extra y ocupando más eventualmente si el
868 \layout Subsubsection
871 \begin_inset LatexCommand \label{sub:repr-class}
878 Las clases son seguramente las estructuras más complejas.
879 Basadas en las estructuras, le agregan datos de control para implementar
880 herencia y polimorfismo.
881 Para esto debe almacenarse, además de los elementos (no estáticos, o sea
882 de instancia) como en el struct, un puntero a una tabla virtual (vtable)
883 y un monitor, ocupando 4 bytes cada uno.
884 El monitor no está bien especificado para qué sirve, pero supongo que debe
885 estar relacionado al recolector de basura.
886 La tabla virtual, a su vez, está compuesta por un puntero a la instancia
887 de una clase ClassInfo (que guarda datos de la clase en sí) y por todos
888 los punteros a métodos virtuales (para implementar polimorfismo).
889 Los atributos estáticos (de clase), como ya se mencionó, se almacenan como
890 variables globales, ya que se conocen en tiempo de compilación.
891 \layout Subsubsection
896 Los punteros a funciones se almacenan como un puntero común y corriente,
901 de la función se conoce en tiempo de compilación y se sabe la cantidad
902 de datos que se deben apilar y desapilar al hacer el llamado, por lo que
903 todo ese código puede hacerse en tiempo de compilación independientemente
904 de donde se encuentre el código de la función a ejecutar.
905 \layout Subsubsection
910 Los delegados deben tener la información del contexto, es por esto que ocupan
911 8 bytes (en x86), 4 para el puntero al código de la función y 4 para el
912 puntero al contexto (sea una instancia de clase o un
917 Esto se comprobó empíricamente ya que no está definido aún.
923 D es un lenguaje imperativo compilado, por lo que se basa en el modelo de
924 Von-Newman y sus 3 operaciones básicas:
936 El llamado a funciones se hace a través de la pila, ya que soporta recursión
937 y hay una pila por cada hilo, ya que soporta múltiples hilos.
938 Además de la cadena dinámica (para el llamado recursivo) tiene cadena estática,
939 ya que soporta funciones anidadas, con el modelo estático, que busca las
944 de la función y no en la función apilada inmediatamente arriba.
948 \begin_inset LatexCommand \label{sub:Punteros}
955 Este lenguaje soporta punteros y referencias, aunque estas últimas son implícita
956 s (el compilador decide cuando usar una referencia y cuando una copia).
957 En términos generales, las instancias de clase siempre se referencian a
958 través de una referencia (jamás se copia un objeto implícitamente).
959 Como se explicó en la sección
960 \begin_inset LatexCommand \vref{sub:Operaciones}
964 , se proveen operaciones para tomar la dirección de una variable (su
968 ) y desreferenciamiento y aritmética de punteros.
969 Además se pueden convertir punteros de forma implícita siguiendo algunas
971 Por ejemplo cualquier puntero puede ser convertido implícitamente a un
976 (sin tipo) o a un puntero a una clase ancestro (si es una instancia de
978 También se ha dicho que, al igual que en C, hay una relación muy estrecha
979 entre puntero y array, por lo que cualquier array puede ser convertido
980 implícitamente a un puntero.
984 \begin_inset LatexCommand \label{sub:Recolección-de-basura}
988 Recolección de basura
991 D provee un recolector de basura, aunque aún no hay muchas definiciones
992 con respecto a su tipo.
993 Por el tipo de API que se provee para controlar el recolector de basura,
1002 ya que se proveen funciones para agregar raíces y también parece implementar
1003 algún tipo de algoritmo generacional ya que además de proveer un método
1004 para realizar una recolección completa, provee uno para realizar una recolecció
1008 Aunque no parece haber nada definido aún con respecto al recolector de basura
1009 (más que estudiar empíricamente la implementación actual o basarse en lo
1010 que provee la biblioteca estándar para manipular al recolector), se menciona
1011 en varios lugares que el ciclo de colección sólo puede ser lanzado cuando
1012 se intenta alocar nueva memoria.
1013 Es decir, que se puede confiar en que el recolector no va a interrumpir
1014 la ejecución del programa en un fragmento de código en el que no se aloca
1016 De cualquier manera, la biblioteca estándar también provee métodos para
1017 desactivar momentáneamente al recolector, por si hay partes críticas del
1018 programa que no deban ser interrumpidas.
1021 Además se menciona que el ciclo de recolección debe correr solo; es decir,
1022 que mientras corre el ciclo de recolección no puede haber ningún otro hilo
1023 del programa corriendo al mismo tiempo (cosa que tiene mucho sentido, de
1024 otra forma sería virtualmente imposible seguir el rastro de la memoria).
1025 \layout Subsubsection
1030 D se enfrenta a un problema poco común en la recolección de basura, ya que
1031 la mayor parte de los lenguajes que lo implementan no permiten un manejo
1032 de bajo nivel de la memoria.
1033 Hay varias circunstancias en las cuales el recolector de basura de D puede
1035 Veamos algunos casos:
1047 En este caso, el comportamiento es indefinido ya que el recolector no verifica
1048 raíces que no sean punteros.
1052 void* p = cast(void*)12345678;
1055 Si por casualidad la dirección de memoria está siendo manejada por el recolector
1056 de basura, estamos ante un problema.
1057 Otros caso que podrían resultar un tanto confuso es que no se puede confiar
1058 en que un puntero conserve la dirección a la que apunta de forma invariante,
1059 ya que el recolector de basura puede moverlo.
1060 Por lo tanto un código como el siguiente:
1072 tiene un comportamiento aleatorio.
1073 Y esto sólo por nombrar algunos problemas que puede acarrear el manejo
1074 de bajo nivel de la memoria usando un recolector de basura.
1075 Claro que si uno necesita un manejo de tan bajo nivel, para estos casos
1076 se puede usar memoria no administrada por el recolector.
1080 \begin_inset LatexCommand \label{sub:Rutinas}
1087 D provee varios tipos de rutinas, aunque todos basado en el mismo tipo básico,
1089 \layout Subsubsection
1091 Funciones planas (sin contexto)
1094 Estas son las funciones más básicas.
1095 Son funciones de nivel 0 (en cuanto a anidamiento) o estáticas (ya sean
1096 anidadas o de clase), por lo que no necesitan de un contexto (cadena estática)
1097 más que la ubicación de la porción de variables globales (estáticas).
1098 Toman exactamente la cantidad de parámetros que se especifica en su declaración.
1101 Por supuesto estás funciones tienen acceso solamente a las variables estáticas
1102 (conocidas en tiempo de compilación y almacenadas en el bloque de datos
1103 del programa), ya sean variables estáticas locales de una función o variables
1104 estáticas de clase (recordar que son todas variables globales con un
1109 \layout Subsubsection
1111 Funciones con contexto
1114 Como ya hemos visto, en D hay algunas funciones que necesitan un
1119 En esta categoría caen tanto los métodos de una instancia de clase como
1120 las funciones anidadas.
1123 En el caso de los métodos es muy claro y simple, además de la función, se
1124 necesita saber sobre qué objeto se está aplicando, así que simplemente
1125 se agrega a los parámetros declarados un puntero (o referencia) a una instancia
1129 Con las funciones anidadas puede resultar un poco más confuso.
1130 Estás funciones necesitan el
1138 (lexicográficamente hablando) para poder obtener sus variables locales.
1139 Podría pensarse entonces, como si estás funciones agregan un parámetro
1140 extra con el puntero a ese
1145 \layout Subsubsection
1150 Las funciones virtuales tienen la particularidad de no conocerse su dirección
1151 de memoria en tiempo de compilación, por lo tanto es necesario agregar
1152 un nivel de indirección al llamarlas.
1153 Es por esto también que es imposible que exista algún tipo de función virtual
1154 sin contexto, ya que debe haber algún contexto que indique, como mínimo,
1155 la dirección de la función a llamar.
1156 D provee funciones virtuales solamente como métodos de instancias de clase
1157 y lo hace de forma implícita (queda en manos del compilador determinar
1158 si una función debe ser virtual o no), es por esto que guarda, como se
1159 explicó en la sección
1160 \begin_inset LatexCommand \vref{sub:repr-class}
1164 , una tabla virtual, en donde se almacena el puntero a cada función virtual
1166 Entonces para llamar a una función virtual, se obtiene el objeto al que
1171 ) que tiene una tabla virtual.
1172 El offset de esa función en la tabla virtual sí se conoce en tiempo de
1173 compilación así que simplemente se ejecuta la función apuntada por vtable+4+off
1174 set (el 4 es porque lo primero que se almacena en la vtable es el puntero
1175 al objeto de tipo ClassInfo).
1176 \layout Subsubsection
1178 Pasaje de parámetros
1181 Las funciones toman parámetros, que son siempre por copia en su implementación
1183 El pasaje por referencia se resuelve al igual que en C, utilizando punteros.
1184 Hay un caso muy particular en D, que son las clases, que siempre son pasadas
1186 Es decir, una variable de clase (que referencia una instancia de una clase)
1187 es siempre de tipo puntero, aunque sintácticamente sea utilizada como una
1188 variable común, semánticamente se comporta como un puntero.
1191 Varias veces se menciona que los parámetros se copian si hay escritura (
1195 ) en la documentación de D, pero se comprobó empíricamente que, como se
1196 especifica en la sección de manejo de memoria, la copia por demanda se
1197 realiza solamente en la biblioteca estándar, no es algo que provea el lenguaje.
1198 \layout Subsubsection
1200 Funciones con parámetros variables
1203 Además soporta, al igual que C, parámetros variables, simplemente proveyendo
1204 métodos para obtener variables de la pila arbitrariamente.
1205 Es decir, a la hora de compilarse un llamado a una rutina con parámetros
1206 variables, se apilan todos los parámetros, se hace el
1210 , y luego se desapilan.
1211 La función llamada tiene entonces, métodos para obtener esos parámetros
1212 extra que no figuraban en la declaración de la función.
1213 \layout Subsubsection
1216 \begin_inset LatexCommand \label{sub:Sobrecarga-de-funciones}
1220 Sobrecarga de funciones
1223 D permite sobrecargar funciones.
1224 Es decir, tener 2 funciones con el mismo nombre pero distintas firmas (cantidad
1225 y/o tipo de parámetros).
1226 Al igual que C++, no permite sobrecargar por el tipo de retorno solamente,
1227 ya que por proveer conversiones implícitas sería imposible desambiguar
1229 Por supuesto esto también debe poder traducirse a funciones planas por
1230 lo que debe haber una forma de identificar unívocamente a cada función
1231 (con un nombre único, asociado a su dirección de memoria).
1232 Para esto se utiliza una técnica conocida como
1236 , que consiste en transformar los nombres de funciones a un nombre único,
1237 aunque no hay ninguna definición aún al respecto de como debe hacerlo D
1238 (fundamental para poder interactuar entre distintos compiladores, ya que
1239 de otra manera no podría encontrar los símbolos en código objeto compilado
1240 por otro compilador).
1243 Entonces el compilador, a la hora de evaluar la dirección de una función
1244 sobrecargada, debe fijarse su nombre y sus parámetros, hacer el
1248 para obtener su identificador único y ahora si proseguir como si fuera
1249 un función común y corriente.
1252 Estructura del programa
1255 La estructura general de un programa D es muy similar a la de uno en C++.
1256 Simplemente se compone de funciones y tipos definidos por el usuario.
1257 Existe una función especial llamada
1261 que es el punto de partida del programa, indispensable a menos que estemos
1262 construyendo una biblioteca.
1268 D elimina el preprocesador e incorpora el concepto de módulo (a diferencia
1269 de C++ que utiliza espacios de nombre).
1270 El módulo tiene alcance de archivo y tiene correspondencia 1 a 1 con la
1271 ruta y nombre del archivo.
1272 Por ejemplo el módulo
1281 A la ruta representada como módulo se la llama
1285 ; es decir, el módulo
1289 pertenece al paquete
1294 El módulo entonces provee un espacio de nombres, cuyos símbolos pueden
1295 ser importados en otros módulos.
1317 void func(modulo2.C c)
1361 func(new modulo2.C);
1370 Como se puede observar, no es imperativo poner el modulo al que pertenece
1371 un símbolo, a menos que se lo quiera desambiguar (si hay 2 símbolos con
1372 el mismo nombre en 2 módulos distintos).
1375 Compilación condicional
1378 Al no proveer un precompilador, D provee un mecanismo de compilación condicional
1379 directamente incluida en el lenguaje.
1380 Simplemente se agregan bloques de código que se compilan solamente si se
1381 le pasa un cierto parámetro al compilador indicando que porción compilar.
1382 Este concepto va un poco más allá, ya que hay compilación condicional incluso
1383 de bloques no son puestos explícitamente como tales, como los bloques de
1384 invariante de representación de una clase o de pre y post condiciones de
1395 version (DEBUG) printf(
1396 \begin_inset Quotes eld
1399 entrando a optimización
1400 \begin_inset Quotes erd
1412 D además provee varios identificadores de versión predefinidos, como la
1417 , sistema operativo, etc.
1420 Además provee otros métodos, como
1436 , pero son todas vueltas de tuerca sobre el mismo concepto.
1440 \begin_inset LatexCommand \label{sub:Assembly-embebido}
1447 D, al igual que C, permite embeber assembly en el lenguaje.
1448 Esto es útil para hacer código de alta performance para fragmentos críticos,
1449 ya que D está pensando como un lenguaje de alta performance y apto para
1450 el desarrollo de aplicaciones de sistema (como controladores, etc).
1454 \begin_inset LatexCommand \label{sec:Orientación-a-objetos}
1458 Orientación a objetos
1461 Como ya se ha mencionado, D provee orientación a objetos principalmente
1462 a través de el tipo class (ver sección
1463 \begin_inset LatexCommand \vref{sub:tipo-class}
1467 ), pero provee algunos mecanismos también a través de los módulos o struct.
1473 La abstracción de datos puede darse a nivel de class, struct o module.
1474 Ambos proveen mecanismos para poder efectuar operaciones sobre un dato
1476 En el caso de struct y class es exactamente igual en cuanto a abstracción.
1477 El módulo es un poco diferente ya que hay sólo una instancia del mismo
1478 (es decir, todos sus datos son estáticos), pero también puede servir para
1480 D provee sintaxis acoplada (
1484 ) a través del operador de
1489 \begin_inset Quotes eld
1493 \begin_inset Quotes erd
1496 , que se utiliza tanto para class como para struct y module.
1497 El module, al no ser un tipo en sí, no soporta sintaxis desacoplada (
1502 Lo mismo pasa con los métodos estáticos de clase.
1505 Todos los objetos en D son con estado explícito, aunque pueden
1517 , pero esto no hace se se resuelvan en tiempo de compilación, en realidad
1518 tienen estado sólo que el compilador no deja que se modifique.
1519 Es decir, no hay forma de tener abstracción declarativa.
1520 \layout Subsubsection
1525 D provee un mecanismo muy interesante y práctico, las propiedades.
1526 Una clase (o estructura) puede tener métodos especiales que pueden ser
1527 llamados como si fueran atributos de la clase.
1528 No es más que azúcar sintáctico pero es muy útil y está implementado de
1529 una forma muy simple.
1530 Cualquier método que tenga un sólo argumento y devuelva un valor del mismo
1531 tipo se convierte en una propiedad de escritura y cualquier método que
1532 no tome argumentos y devuelva un valor se convierte en una propiedad de
1534 Incluyendo ambos se pueden tener propiedades de lectura/escritura.
1547 int read() { return _i; }
1550 int write(int i) { return _i = i; }
1553 int rw() { return _i; }
1556 int rw(int i) { return _i = i; }
1571 // c.read = 1; NO COMPILA
1582 // printf("c.read = %d
1584 n", c.write); NO COMPILA
1601 Además todos los tipos básicos poseen propiedades, algunas comunes a todos
1606 , que devuelve su tamaño, en general estos son todos resueltos en tiempo
1607 de compilación) y otros particulares de cada tipo (como
1611 para los array, que devuelve la cantidad de elementos que almacena).
1612 \layout Subsubsection
1614 Sobrecarga de operadores
1617 Otro mecanismo importante de abstracción que provee D es la sobrecarga de
1619 Se puede sobrecargar los operadores de clases y estructuras, de manera
1620 tal de hacerlos ver sintácticamente como tipos nativos del lenguaje.
1621 También es azúcar sintáctico y un caso particular de sobrecarga de funciones
1623 \begin_inset LatexCommand \pageref{sub:Sobrecarga-de-funciones}
1633 D provee mecanismos de seguridad, tanto a nivel de módulo como de clase
1634 y estructuras, aunque se ha comprobado empíricamente que el compilador
1635 no lo está chequeando por el momento.
1636 Por ejemplo, el siguiente código compila y corre:
1672 El único tipo que permite herencia es class (y su sub-tipo interface).
1673 D permite herencia simple entre clases comunes y una herencia múltiple
1674 limitada a través de las interfaces.
1675 Es decir, una clase sólo puede heredar de una sola clase, pero puede implementa
1676 r muchas interfaces.
1682 D implementa polimorfismo principalmente (pero no únicamente) a través de
1683 las clases (e interfaces) y sus funciones virtuales, pero también a través
1684 de la sobrecarga de funciones en general.
1685 \layout Subsubsection
1688 \begin_inset LatexCommand \label{sub:Polimorfismo-estático}
1692 Polimorfismo estático
1695 D provee tipos genéricos, también conocidos en el mundo de los lenguajes
1700 o polimorfismo estático, ya que permite que una función o clase se comporte
1701 de distinta manera pero se resuelve en tiempo de compilación.
1707 D provee un mecanismo de manejo de excepciones, con la sintaxis clásica
1713 D, al igual que C++, dice que el manejo de excepciones puede no ser
1715 performance-critical
1717 , ya que debe manejar sólo casos muy esporádicos, situaciones inesperadas.
1718 D es más consistente en el uso de excepciones que C++, ya que utiliza excepcion
1719 es en muchos lugares en la biblioteca estándar, cosa que C++ no suele hacer
1720 y por lo cual el manejo de excepciones en ese lenguaje no suele ser muy
1724 Sin embargo no hay mucho más definido en D que la sintaxis del manejo de
1725 excepciones, nada se define sobre el mecanismo (excepto en Windows, donde
1728 Microsoft Windows Structured Exception Handling
1731 Es por eso que me limitaré a ejemplificar el manejo de excepciones a un
1753 throw new Exception("first");
1770 throw new Exception("second");
1805 pueden estar anidados.
1808 Paralelismo / Concurrencia
1811 D provee algunas pocas primitivas para el soporte de concurrencia.
1812 En la biblioteca estándar provee una clase para ejecutar múltiples hilos
1813 y provee en el lenguaje la palabra reservada
1817 para agregar bloqueo y desbloqueo de exclusión mutua (
1821 ) automáticamente antes y después (respectivamente) de bloque que encierra.
1822 También puede usarse como clasificador de almacén (es decir, para proteger
1823 una variable) o como modificador de una función (para proteger dicha función)
1824 o de clase o de cualquier otra sentencia.
1827 Es necesario utilizar la clase
1831 para ejecutar múltiples hilos ya que el recolector de basura tiene que
1832 saber de todos los hilos que están corriendo para poder administrar su
1833 memoria (y frenarlos ante un ciclo de recolección), aunque técnicamente
1834 podría evitarse ya que se puede acceder a cualquier biblioteca de C (incluyendo
1839 \begin_inset LatexCommand \label{sec:Programación-segura}
1846 Uno de los objetivos principales de D es implementar técnicas de programación
1847 segura, para tratar de evitar (o al menos detectar) la mayor cantidad de
1848 errores de manera simple.
1849 Veamos entonces algunos mecanismos que provee para satisfacer este objetivo.
1852 Programación por contrato
1855 La programación por contrato consiste en imponer ciertas reglas que se cumplan
1856 en distintos momentos del programa.
1857 Básicamente provee 3 conceptos para verificar estos
1865 , invariantes de representación y pre y post condiciones.
1866 Esto parece contradecir el objetivo de D de ser un lenguaje de alta performance
1867 , ya que si se hacen muchos chequeos, inevitablemente se sacrifica performance.
1868 Pero esto no es necesariamente cierto, ya que todos estos mecanismos pueden
1869 ser desactivados en tiempo de compilación, logrando tener un código para
1870 depuración muy robusto y lleno de chequeos y un código para producción
1871 muy eficiente y rápido.
1872 \layout Subsubsection
1877 Este es el tipo más básico de contrato, provisto también de una forma más
1878 primitiva por C (a través del precompilador).
1879 Simplemente evalúa en tiempo de ejecución que una expresión evalúe a
1884 Si no es así, simplemente el programa lanza una excepción.
1885 \layout Subsubsection
1887 Invariante de representación
1890 Las clases puede incluir un invariante de presentación.
1891 Esto es un fragmento de código que se ejecuta cada vez que se cambia una
1892 instancia de la clase (excepto cuando los cambios se realizan desde una
1894 Esto permite asegurar que los objetos estén siempre en estado consistente,
1895 mientras se ejecute código que no conoce su representación.
1917 assert(1 <= dia && dia <= 31);
1920 assert(1 <= mes && mes <= 12);
1935 dia = 50; // ok, dentro de la clase no se chequea
1952 Fecha f = new Fecha;
1958 f.dia = 40; // error!
1959 \layout Subsubsection
1961 Pre y post condiciones
1964 Toda función puede tener, además de su cuerpo, un bloque de código de pre-condic
1965 iones y/o un bloque de código de post-condiciones, que será ejecutado antes
1966 y/o después de ejecutar la función (respectivamente).
1991 assert((result * result) == x);
2003 return cast(long) std.math.sqrt(cast(float) x);
2009 El parámetro del bloque
2013 es el valor devuelto por el cuerpo de la función.
2014 Entonces cuando se llame a
2018 , el compilador (a menos que esté en modo
2025 assert(8 >= 0); // ok
2028 long tmp = raiz(8); // devuelve 2 por la conversión a long
2031 assert((2 * 2) == 8); // error!
2037 D provee dentro del lenguaje herramientas para realizar casos de prueba
2042 ) para asegurarse que una clase se comporte como debe.
2043 Este código se ejecuta cuando se inicia el programa si se compila con la
2070 static bit ok() { return false; }
2076 Un programa que use esta clase saldrá apenas se inicia con una excepción
2087 Para analizar si el lenguaje cumple sus objetivos, vamos a analizar esos
2088 objetivos (ver página
2089 \begin_inset LatexCommand \pageref{sub:Objetivo-del-lenguaje}
2094 Para el análisis se asume que todo lo propuesto en el lenguaje está correctamen
2095 te implementado (que, como vimos a lo largo de este documento, no es necesariame
2099 Reducir el costo de desarrollo en al menos un 10% agregando características
2100 que mejoren la productividad y ajustando las características del lenguaje
2101 para que los errores más comunes que más cuestan reparar sean evitados
2105 Es difícil evaluar la ganancia en el costo de desarrollo (más aún si no
2106 está claro en comparación a qué se quiere reducir el costo), pero sin dudas
2107 el disponer de un recolector de basura, propiedades y otras muchas característi
2108 cas muy deseables deben reducir de forma considerable el costo de desarrollo.
2111 Con respecto a los mecanismos para evitar los errores más comunes, por lo
2112 que he probado del lenguaje parece cumplirlo bastante bien, si uno se toma
2113 el trabajo de utilizar todas las herramientas que se le provee, en particular
2114 de las comentadas en la sección
2115 \begin_inset LatexCommand \vref{sec:Programación-segura}
2122 En términos generales podría decirse que sí, cumple este objetivo.
2125 Hacer más fácil escribir programas portables entre compiladores, arquitecturas
2126 y sistemas operativos.
2129 Soportar programación multi-paradigma; es decir, como mínimo, soportar los
2130 paradigmas: imperativo, estructurado, orientado a objetos y programación
2134 Definitivamente cumple con estos objetivos mínimos, es un lenguaje netamente
2135 imperativo, con soporte de estructuras y todos los requerimientos de la
2136 programación orientada a objetos (a través de las clases, ver sección
2137 \begin_inset LatexCommand \vref{sec:Orientación-a-objetos}
2142 Además provee un mecanismo para programación genérica, a través de templates
2144 \begin_inset LatexCommand \vref{sub:Polimorfismo-estático}
2151 Tener una curva de aprendizaje corta para programadores que se sienten a
2155 Aunque tiene varias diferencias con C y C++, la sintaxis es muy similar
2156 y su uso en general también.
2157 Particularmente encuentro bastante molesto y confuso que las instancias
2158 de clase se manejen por referencia (en realidad encuentro confuso que sean
2160 A pesar de esto, sin dudas la curva de aprendizaje es corta (aunque no
2161 nula), así que creo que este objetivo también lo cumple satisfactoriamente.
2164 Proveer acceso irrestricto de bajo nivel cuando sea necesario.
2167 Definitivamente también lo cumple.
2168 Soporta punteros (pág.
2170 \begin_inset LatexCommand \pageref{sub:Punteros}
2174 ), assembly embebido (pág.
2176 \begin_inset LatexCommand \pageref{sub:Assembly-embebido}
2180 ), alocación de memoria manual (pág.
2182 \begin_inset LatexCommand \pageref{sub:Variables}
2186 ), control sobre el recolector de basura (pág.
2188 \begin_inset LatexCommand \pageref{sub:Recolección-de-basura}
2195 Hacer que implementar un compilador sea mucho más sencillo que para C++.
2198 Esto tampoco puede ser evaluado certeramente de forma sencilla, pero viendo
2199 como se simplificaron varias características de C++ que son particularmente
2200 complicadas de implementar (como la herencia múltiple) es de esperarse
2201 que hacer un compilador de D sea más sencillo que uno de C++, pero no podría
2202 afirmarlo porque tampoco conozco las complicaciones que adhiere D con las
2203 características no presentes en C++, como para saber cómo sale en el balance.
2206 Ser compatible con la ABI local de C.
2209 Lo cumple, puede interactuar con C sin inconvenientes.
2212 Tener gramática libre de contexto.
2215 Tampoco es algo que haya podido probar de forma sería, pero se eliminan
2216 construcciones de C que dependían del contexto como
2220 que en C/C++ puede ser interpretado como la resta de
2232 es una variable o como
2248 es un tipo definido por el usuario.
2249 En D esa expresión es la resta, ya que para hacer el
2253 hay que usar el operador:
2260 Entonces, si bien no puedo asegurar que el objetivo esté cumplido, sí puedo
2261 asegurar que está más cercano a tener una gramática menos dependiente del
2265 Escribir fácilmente aplicaciones internacionalizadas.
2268 Tengo la sensación de haber visto en algún momento que había una forma de
2269 poner literales de string internacionalizables en el lenguaje, con el siguiente
2273 \begin_inset Quotes erd
2277 \begin_inset Quotes erd
2283 Esa característica parece que no existe más, al menos en la documentación,
2284 así que realmente no veo de qué manera se cumple este objetivo.
2287 Incorporar Programación por Contrato y metodologías de casos de prueba.
2290 Lo cumple muy bien, utilizando todo lo visto en la sección
2291 \begin_inset LatexCommand \vref{sec:Programación-segura}
2298 Ser capaz de construir programas independientes y livianos.
2301 Los programas son sin dudas menos livianos e independientes que los de C,
2302 porque además de depender de la biblioteca estándar de C (aunque no depende
2303 necesariamente, la biblioteca estándar de D la usa extensivamente), depende
2304 de la biblioteca propia de D, que incluye al código del recolector de basura.
2305 Compilando estáticamente, un programa que no hace nada:
2320 su versión en C y C++ ocupan 460KB, mientras que la versión en D ocupa 1.2MB.
2323 Sin embargo, si hacemos el clásico ejemplo de
2347 Si la versión en C++ la escribimos usando la STL
2353 Standard Template Library (la biblioteca estándar de C++)
2368 std::cout << "hola mundo!
2379 En C sigue ocupa 461KB, en D sigue ocupando 1.2MB y la versión en C++ pasa
2380 a ocupar 1.1MB, lo que pone en evidencia la alta complejidad de la biblioteca
2384 Por lo tanto, si bien D no puede ser tan liviano como C, sí puede sacarle
2385 una buena ventaja a C++ en lo que es el manejo de
2389 u otras estructuras que provee la STL en C++ que son muy complejas.