X-Git-Url: https://git.llucax.com/z.facultad/75.00/informe.git/blobdiff_plain/5f79318a52fc6ada10154cb148008bd9d44fa22e..6c0df59:/source/d.rst?ds=sidebyside diff --git a/source/d.rst b/source/d.rst index 1fd5436..449109b 100644 --- a/source/d.rst +++ b/source/d.rst @@ -2,10 +2,12 @@ .. Introducción y breve reseña del lenguaje de programación D. También se presentan las necesidades particulares de D con respecto al recolector de basura y su estado actual. - ESTADO: TERMINADO + ESTADO: TERMINADO, CORREGIDO (A) -.. _ref_d: +.. highlight:: d + +.. _d_lang: El lenguaje de programación D ============================================================================ @@ -15,27 +17,26 @@ Historia ---------------------------------------------------------------------------- D_ es un lenguaje de programación relativamente joven. Nació en 1999 y el -2 de enero de 2007 salió su `versión 1.0`__. Poco tiempo después se -continúo el desarrollo del lenguaje en la `versión 2.0`__, aún inestable -y en la cual se está experimentando principalmente sobre -multi-procesamiento. +2 de enero de 2007 salió su `versión 1.0`__. Poco tiempo después se continúo +el desarrollo del lenguaje en la `versión 2.0`__, que pasó a ser considerada +estable aproximadamente en junio de 2010 con el lanzamiento del libro "The +D Programming Language" [ALX10]_, pero aún es un trabajo en progreso. __ `D 1.0`_ __ `D 2.0`_ El lenguaje fue diseñado e implementado por `Walter Bright`_, desarrollador -principal de Zortech C++, uno de los primeros compilador de C++ que -compilaba a código nativo, y está fuertemente influenciado éste. Sin -embargo toma muchos conceptos de otros lenguajes de más alto nivel, como -Java_ o incluso lenguajes dinámicos como Perl_. +principal de Zortech C++, uno de los primeros compiladores de C++ que +compilaba a código nativo, y está fuertemente influenciado por éste. Sin +embargo toma muchos conceptos de otros lenguajes de más alto nivel, como Java_ +o incluso lenguajes dinámicos como Perl_, Python_ y Ruby_. El origen del lenguaje está plasmado en su sitio web, en donde se cita: - It seems to me that most of the "new" programming languages fall into - one of two categories: Those from academia with radical new paradigms - and those from large corporations with a focus on RAD and the web. Maybe - it's time for a new language born out of practical experience - implementing compilers. + It seems to me that most of the "new" programming languages fall into one + of two categories: Those from academia with radical new paradigms and those + from large corporations with a focus on RAD and the web. Maybe it's time + for a new language born out of practical experience implementing compilers. Esto podría traducirse como: @@ -45,79 +46,78 @@ Esto podría traducirse como: y web. Tal vez es hora de que nazca un nuevo lenguaje de la experiencia práctica implementando compiladores. -La versión 1.0 fue más bien una etiqueta arbitraria que un indicador real -de estar ante una versión estable y completa. Luego de liberarse se -siguieron agregando nuevas características al lenguaje hasta que se empezó -el desarrollo en paralelo de la versión 2.0 al introducirse el concepto de -inmutabilidad y funciones *puras* [#dpure]_ (a mediados de 2007). +La versión 1.0 fue más bien una etiqueta arbitraria que un indicador real de +estabilidad y completitud. Luego de liberarse se siguieron agregando nuevas +características al lenguaje hasta que se empezó el desarrollo en paralelo de +la versión 2.0 al introducirse el concepto de inmutabilidad y funciones +*puras* [#dpure]_ (a mediados de 2007). .. [#dpure] Por funciones *puras* en D_ se entiende que no tienen efectos - colaterales. Es decir, una función pura siempre que se llame con la - misma entrada producirá el mismo resultado. Esto es análogo a como - funcionan los lenguajes funcionales en general, abríendo la puerta a la - programación de estilo funcional en - D_. + colaterales. Es decir, una función pura siempre que se llame con la misma + entrada producirá el mismo resultado. Esto es análogo a como funcionan los + lenguajes funcionales en general, abriendo la puerta a la programación de + estilo funcional en D_. A partir de este momento la versión 1.0 quedó *teóricamente* congelada, -introduciendo solo cambios que arreglen errores (*bug fixes*), -introduciendo todos las nuevas características solamente en la versión -2.0 del lenguaje. La realidad es que se hicieron cambios incompatibles a la -versión 1.0 del lenguaje en reiteradas ocasiones, pero se fue tendiendo -a cada vez introducir menos cambios incompatibles. Sin embargo al día de -hoy el compilador de referencia sigue teniendo algunas características -presentes en la especificación del lenguaje sin implementar, por lo que -todavía no hay una implementación completa de la versión 1.0 del lenguaje, -siendo esta etiqueta todavía un poco arbitraria. +introduciendo solo cambios que arreglen errores (*bug fixes*), agregando +nuevas características solamente en la versión 2.0 del lenguaje. La realidad +es que se hicieron cambios incompatibles a la versión 1.0 del lenguaje en +reiteradas ocasiones, pero se fue tendiendo a cada vez introducir menos +cambios incompatibles. Sin embargo al día de hoy el compilador de referencia +sigue teniendo algunas características presentes en la especificación del +lenguaje sin implementar, por lo que todavía no hay una implementación +completa de la versión 1.0 del lenguaje. El lenguaje ha sido, hasta el desarrollo de la versión 2.0 al menos, un esfuerzo unipersonal de `Walter Bright`_, dados sus problemas a la hora de -delegar o aceptar contribuciones. Esto motivó a la comunidad de usuarios de -D_ a crear bibliotecas base alternativas a la estándar (llamada Phobos_) en -las cuales se pudiera trabajar sin las trabas impuestas por el autor del -lenguaje. +delegar o aceptar contribuciones. Esto motivó a la comunidad de usuarios de D_ +a crear bibliotecas base alternativas a la estándar (llamada Phobos_) en las +cuales se pudiera trabajar sin las trabas impuestas por el autor del lenguaje. En este contexto nacen primero Mango_ y luego Ares_. Mango_ fue creada por Kris Macleod Bell a principios de 2004 como una biblioteca que provee -servicios básicos de entrada/salida (o *I/O* de *input/output* en inglés) -de alto rendimiento. Siendo estos servicios algo básico lo más natural -hubiera sido que se encuentren en la biblioteca estándar de D_ pero por las +servicios básicos de entrada/salida (o *I/O* de *input/output* en inglés) de +alto rendimiento. Siendo estos servicios algo básico lo más natural hubiera +sido que se encuentren en la biblioteca estándar de D_ pero por las dificultades para contribuir a ésta, se desarrolla como una biblioteca separada. A mediados de 2004 Sean Kelly crea Ares_ , con las mismas -motivaciones pero con la intención de crear una biblioteca base (conocida -en inglés como *runtime*) que incluye los servicios básicos que necesita el +motivaciones pero con la intención de crear una biblioteca base (conocida en +inglés como *runtime*) que incluye los servicios básicos que necesita el lenguaje (información de tipos, manejo de excepciones e hilos, creación y manipulación de objetos, recolector de basura, etc.). Al poco tiempo de liberarse Ares_, Mango_ empieza a utilizarla como biblioteca base. -Para comienzos de 2006, se empieza a trabajar en la combinación de -ambas bibliotecas para lograr una biblioteca estándar alternativa -con un alto grado de cohesión. Finalmente a principios de 2007, -coincidiendo por casualidad con la aparición de D_ 1.0, se anuncia el -resultado de este combinación bajo el nombre de Tango_, proveyendo una -alternativa completa y madura a la biblioteca estándar de D_ Phobos_. -A principios de 2008 los principales desarrolladores de Tango_ (Kris Bell, -Sean Kelly, Lars Ivar Igesund y Michael Parker publican el libro llamado -`Learn to Tango with D`_. - -Esto por un lado fue un gran avance porque dio un impulso muy considerable -al lenguaje pero por otro un gran retroceso, porque todavía al día de hoy -D_ 1.0 tiene 2 bibliotecas base, una estándar pero de peor calidad y menos -mantenida y una alternativa de mayor calidad y apertura a la comunidad -(pero no estándar). El peor problema es que ambas son **incompatibles**, -por lo que un programa hecho con Tango_ no funciona con Phobos_ y viceversa -(a menos que el programador haya invertido una cantidad de tiempo no -trivial en asegurarse de que funcione con ambas). +Para comienzos de 2006, se empieza a trabajar en la combinación de ambas +bibliotecas para lograr una biblioteca estándar alternativa con un alto grado +de cohesión. Finalmente a principios de 2007, coincidiendo por casualidad con +la aparición de `D 1.0`_, se anuncia el resultado de este combinación bajo el +nombre de Tango_, proveyendo una alternativa completa y madura a la biblioteca +estándar de D_ Phobos_. A principios de 2008 los principales desarrolladores +de Tango_ (Kris Bell, Sean Kelly, Lars Ivar Igesund y Michael Parker) publican +el libro llamado `Learn to Tango with D`_ [BKIP08]_. + +Esto por un lado fue un gran avance porque dio un impulso muy considerable al +lenguaje pero por otro un gran retroceso, porque todavía al día de hoy `D +1.0`_ tiene dos bibliotecas base, una estándar pero de peor calidad, menos +mantenida y usada; y una alternativa de mayor calidad y apertura a la +comunidad (pero no estándar). El peor problema es que ambas son +**incompatibles**, por lo que un programa hecho con Tango_ no funciona con +Phobos_ y viceversa (a menos que el programador haya invertido una cantidad de +tiempo considerable en asegurarse de que funcione con ambas). Esto hace que la compatibilidad de programas y bibliotecas esté muy -fragmentada entre las 2 bibliotecas base. Si bien no parece que vaya -a haber solución alguna a este problema para D 1.0, D 2.0 va en camino -a solucionar este problema ya que utiliza DRuntime_, un nuevo intento de -Sean Kelly por proveer una biblioteca *runtime* bien organizada -y mantenida, que es una adaptación de la biblioteca *runtime* de Tango_ -a D 2.0. Si bien todavía Tango_ no fue adaptada a D 2.0, se espera que -cuando esto pase compartan la misma biblioteca *runtime* permitiendo que -bibliotecas y programas hechos para Tango_ y Phobos_ 2.0 puedan coexistir -sin problemas. +fragmentada entre las dos bibliotecas base. Si bien no parece que vaya a haber +solución alguna a este problema para `D 1.0`_, `D 2.0`_ va en camino +a solucionar este problema ya que utiliza DRuntime_, un nuevo intento de Sean +Kelly por proveer una biblioteca *runtime* bien organizada y mantenida, que es +una adaptación de la biblioteca *runtime* de Tango_ a `D 2.0`_. Sin embargo +Tango_ no fue adaptada a `D 2.0`_ todavía, y no hay muchas perspectivas de que +sea portada en algún momento, por un lado porque en general la comunidad sigue +fragmentada entre muchos usuarios de `D 1.0`_ que no están contentos con los +cambios introducidos en `D 2.0`_, en su mayoría usuarios de Tango_, y que no +planean migrar a esa versión; y por otro porque el desarrollo de Phobos_ 2.0 +se ha abierto mucho y tiene muchos colaboradores, por lo tanto la mayor parte +de la gente que utiliza `D 2.0`_ está contenta con el estado de Phobos_ 2.0. Descripción general @@ -125,29 +125,29 @@ Descripción general D_ es un lenguaje de programación con sintaxis tipo C, multi-paradigma, compilado, con *tipado* fuerte y estático, buenas capacidades tanto de -programación de bajo nivel (*system programming*) como de alto nivel. Es -compatible de forma binaria con C (se puede enlazar código objeto C con +programación de bajo nivel (*system programming*) como de alto nivel; además +es compatible de forma binaria con C (se puede enlazar código objeto C con código objeto D). Con estas características, D_ logra llenar un vacío -importante que hay entre lo lenguajes de alto bajo nivel y los de alto -nivel [BKIP08]_. Si bien tiene herramientas de muy bajo nivel, que por lo -tanto son muy propensas a errores, da una infinidad de mecanismos para -evitar el uso de estas herramientas a menos que sea realmente necesario. -Además pone mucho énfasis en la programación confiable, para lo cual provee -muchos mecanismos para detectar errores en los programas de forma temprana. - -Si puede pensarse en C++ como un "mejor C", podría decirse que D_ es -un "mejor C++", ya que el objetivo del lenguaje es muy similar a C++, -pero implementa muchas características que jamás pudieron entrar en -el estándar de C++ y lo hace de una forma mucho más limpia, ya que -no debe lidiar con problemas de compatibilidad hacia atrás, y cuenta -con la experiencia del camino recorrido por C++, pudiendo extraer de -él los mejores conceptos pero evitando sus mayores problemas también. +importante que hay entre lo lenguajes de alto bajo nivel y los de alto nivel +[BKIP08]_. Si bien tiene herramientas de muy bajo nivel, que por lo tanto son +muy propensas a errores, da una infinidad de mecanismos para evitar el uso de +estas herramientas a menos que sea realmente necesario. Además pone mucho +énfasis en la programación confiable, para lo cual provee muchos mecanismos +para detectar errores en los programas de forma temprana. + +Si puede pensarse en C++ como un "mejor C", podría decirse que D_ es un "mejor +C++", ya que el objetivo del lenguaje es muy similar a C++, pero implementa +muchas características que jamás pudieron entrar en el estándar de C++ y lo +hace de una forma mucho más limpia, ya que no debe lidiar con problemas de +compatibilidad hacia atrás, y cuenta con la experiencia del camino recorrido +por C++, pudiendo extraer de él los mejores conceptos pero evitando sus +mayores problemas. Otra gran diferencia con C++ es la facilidad para ser analizado -gramaticalmente (*parsing*), ya fue especialmente diseñado para ser -sencillo y a diferencia de C y C++ su gramática es independiente del -contexto (*context-free grammar*). Esto permite que D pueda ser compilado -en pequeños pasos bien separados: +sintácticamente (*parsing*), ya que fue especialmente diseñado para ser +sencillo y a diferencia de C y C++ su gramática es independiente del contexto +(*context-free grammar*). Esto permite que D pueda ser compilado en pequeños +pasos bien separados: 1. Análisis léxico. 2. Análisis sintáctico. @@ -155,25 +155,25 @@ en pequeños pasos bien separados: 4. Optimizaciones. 5. Generación de código. -Esto favorece la creación de herramientas dada la facilidad de usar -solamente la cantidad de análisis necesario para cada herramienta (por -ejemplo un editor de textos puede tener hasta análisis sintáctico para -proveer resaltado o un entorno de desarrollo puede proveer herramientas de -re-factorización de código haciendo uso del análisis semántico). - +Esto favorece la creación de herramientas dada la facilidad de usar solamente +la cantidad de análisis necesario para cada una (por ejemplo un editor de +textos puede tener hasta análisis sintáctico para proveer resaltado o un +entorno de desarrollo puede proveer herramientas para re-factorizar el código +haciendo uso del análisis semántico). -Una de las características que nunca pudo entrar en el estándar de C++ -es la recolección de basura. D_ no comete el mismo error. +Una de las características que nunca pudo entrar en el estándar de C++ es la +recolección de basura. D_ no comete el mismo error. Características del lenguaje ---------------------------------------------------------------------------- -A continuación se enumeran las principales características de D_, -agrupadas por unidades funcional o paradigmas que soporta: +A continuación se enumeran las principales características de D_, agrupadas +por unidades funcionales o paradigmas que soporta: + -.. _ref_d_generic: +.. _d_generic: Programación genérica y meta-programación ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -181,25 +181,25 @@ Programación genérica y meta-programación La programación genérica se trata de la capacidad de poder desarrollar algoritmos y estructuras independientes de los tipos que manipulan (pero de forma segura o *type-safe*). Esto fue muy popularizado por C++ gracias a su -soporte de plantillas (*templates*) y luego otros lenguajes como Java_ -y `C#`_ lo siguieron. Sin embargo otros lenguajes proveen formas más -avanzadas de programación genérica, gracias a sistemas de tipos más -complejos (como Haskell_). - -La meta-programación se refiere en general a la capacidad de un lenguaje -para permitir generar código dentro del mismo programa de forma automática. -Esto permite evitar duplicación de código y fue también muy popularizado -por el soporte de *templates* de C++, aunque muchos otros lenguajes tienen -mejor soporte de meta-programación, en especial los lenguajes dinámicos -(como Python_). +soporte de plantillas (*templates*) y luego otros lenguajes como Java_ y `C#`_ +lo siguieron. Sin embargo otros lenguajes proveen formas más avanzadas de +programación genérica, gracias a sistemas de tipos más complejos (como +Haskell_). + +La meta-programación se refiere en general a la capacidad de un lenguaje para +permitir generar código dentro del mismo programa de forma automática. Esto +permite evitar duplicación de código y fue también muy popularizado por el +soporte de *templates* de C++, aunque muchos otros lenguajes tienen mejor +soporte de meta-programación, en especial los lenguajes dinámicos (como +Python_). D_ provee las siguientes herramientas para realizar programación genérica y meta-programación: -``if`` estático (``static if``): - puede verse como similar a la directiva del preprocesador de C/C++ - ``#if``, pero a diferencia de esto, en D_ el ``static if`` tiene acceso - a todos los símbolos del compilador (constantes, tipos, variables, etc). +``if`` estático (``static if``) + puede verse como similar a la directiva del preprocesador de C/C++ ``#if``, + pero a diferencia de esto, en D_ el ``static if`` tiene acceso a todos los + símbolos del compilador (constantes, tipos, variables, etc). Ejemplo:: @@ -208,9 +208,9 @@ y meta-programación: Más información en http://www.digitalmars.com/d/1.0/version.html#staticif -Inferencia de tipos básica implícita y explícita (mediante ``typeof``): - si no se especifica un tipo al declarar una variable, se infiere del - tipo de su inicializador. +Inferencia de tipos básica implícita y explícita (mediante ``typeof``) + si no se especifica un tipo al declarar una variable, se infiere del tipo + de su valor de inicialización. Ejemplo:: @@ -221,8 +221,8 @@ Inferencia de tipos básica implícita y explícita (mediante ``typeof``): Más información en http://www.digitalmars.com/d/1.0/declaration.html#AutoDeclaration - Mediante el uso de ``typeof`` se puede solicitar el tipo de una - expresión arbitraria. + Mediante el uso de ``typeof`` se puede solicitar el tipo de una expresión + arbitraria. Ejemplo:: @@ -230,10 +230,10 @@ Inferencia de tipos básica implícita y explícita (mediante ``typeof``): Más información en http://www.digitalmars.com/d/1.0/declaration.html#typeof -Iteración sobre colecciones (``foreach``): +Iteración sobre colecciones (``foreach``) cualquier tipo de colección (arreglos estáticos y dinámicos, arreglos - asociativos, clases, estructuras o delegados) puede ser iterada mediante - la sentencia ``foreach``. + asociativos, clases, estructuras o delegados) puede ser iterada mediante la + sentencia ``foreach``. Ejemplo:: @@ -242,12 +242,12 @@ Iteración sobre colecciones (``foreach``): foreach (i; a) total += i; -*Templates*: - clases y funciones pueden ser parametrizadas. Esto permite desarrollar - algoritmos genéricos sin importar el tipo de los datos de entrada, - siempre y cuando todos los tipos tengan una *interfaz* común. Esto - también es conocido como *polimorfismo en tiempo de compilación*, y es - la forma más básica de programación genérica. +*Templates* + clases y funciones pueden ser generalizadas. Esto permite desarrollar + algoritmos genéricos sin importar el tipo de los datos de entrada, siempre + y cuando todos los tipos tengan una *interfaz* común. Esto también es + conocido como *polimorfismo en tiempo de compilación*, y es la forma más + básica de programación genérica. Ejemplo:: @@ -255,12 +255,11 @@ Iteración sobre colecciones (``foreach``): auto i = sumar!(int)(5, 6); // i == 11 auto f = sumar!(float)(5, 6); // j == 11.0f - Además se pueden definir bloques de declaraciones parametrizados (esto - no es posible en C++), permitiendo instanciar dicho bloque con - parámetros particulares. Esto sirve como un mecanismo para la - reutilización de código, ya que puede incluirse un mismo bloque en - distintos lugares (por ejemplo clases). Un bloque parametrizado puede - verse como una especie de módulo. + Además se pueden definir bloques de declaraciones generalizadas (esto no + es posible en C++), permitiendo instanciar dicho bloque con parámetros + particulares. Esto sirve como un mecanismo para la reutilización de código, + ya que puede incluirse un mismo bloque en distintos lugares (por ejemplo + clases). Un bloque generalizado puede verse como una especie de módulo. Ejemplo:: @@ -272,26 +271,26 @@ Iteración sobre colecciones (``foreach``): bloque!(int, float).x = 5; float f = bloque!(int, float).foo(7); - La utilidad más prominente de los bloques parametrizados se da al + La utilidad más prominente de los bloques generalizados se da al acompañarse de *mixins*. -Instanciación implícita de funciones parametrizadas: +Instanciación implícita de funciones generalizadas el lenguaje es capaz de deducir los parámetros siempre que no hayan - ambigüedades + ambigüedades. Ejemplo:: auto i = sumar(5, 6); // i == 11 auto f = sumar(5.0f, 6.0f); // f == 11.0f -Especialización explícita y parcial de *templates*: - la especialización de *templates* consiste, al igual que en C++, en - proveer una implementación especializada para un tipo de dato (o valor) - de los parámetros. Especialización parcial se refiere a la capacidad - de especializar un parámetro a través de un subtipo. Por ejemplo, se - puede especializar un *template* para cualquier tipo de puntero, o para - cualquier tipo de arreglo dinámico, sin necesidad de especificar el tipo - al que apunta dicho puntero o el tipo almacenado por el arreglo. +Especialización explícita y parcial de *templates* + la especialización de *templates* consiste, al igual que en C++, en proveer + una implementación especializada para un tipo de dato (o valor) de los + parámetros. Especialización parcial se refiere a la capacidad de + especializar un parámetro a través de un subtipo. Por ejemplo, se puede + especializar un *template* para cualquier tipo de puntero, o para cualquier + tipo de arreglo dinámico, sin necesidad de especificar el tipo al que + apunta dicho puntero o el tipo almacenado por el arreglo. Ejemplo de especialización:: @@ -307,25 +306,25 @@ Especialización explícita y parcial de *templates*: float v = 5.0f, w = 6.0f; auto f = sumar(&v, &w); // f == 11.0f -Tipos, valores (incluyendo *strings*) y *templates* como parámetros: +Tipos, valores (incluyendo *strings*) y *templates* como parámetros esto es otro bloque de construcción importantísimo para la programación genérica en D, ya que combinando *templates* que toman *strings* como - parámetro en combinación con *string mixins* pueden hacerse toda clase - de meta-programas. + parámetro en combinación con *string mixins* pueden hacerse toda clase de + meta-programas. Ejemplo:: template hash(string s, uint so_far=0) { static if (s.length == 0) - const hash = sofar; + const hash = so_far; else - const hash = hash!(s[1 .. length], sofar * 11 + s[0]); + const hash = hash!(s[1 .. length], so_far * 11 + s[0]); } string s = hash!("hola"); // calculado en tiempo de compilación -Cantidad de parámetros variables para *templates*: - Esto permite implementar tuplas u otros algoritmos que inherentemente - deben tomar parámetros variables en tiempo de compilación. +Cantidad de parámetros variables para *templates* + Esto permite implementar tuplas u otros algoritmos que inherentemente deben + tomar una cantidad variable de parámetros en tiempo de compilación. Ejemplo:: @@ -337,14 +336,13 @@ Cantidad de parámetros variables para *templates*: } double d = sumar(1, 2.0, 3.0f, 4l); // d == 10.0 -*CTFE* (*compile-time function execution*): +*CTFE* (*compile-time function execution*) si una función cumple ciertas reglas básicas (como por ejemplo no tener - efectos colaterales) puede ser ejecutada en tiempo de compilación en vez - de tiempo de ejecución. Esto permite hacer algunos cálculos que no - cambian de ejecución en ejecución al momento de compilar, mejorando la - performance o permitiendo formas avanzadas de metaprogramación. Esta - característica se vuelve particularmente útil al combinarse con *string - mixins*. + efectos colaterales) puede ser ejecutada en tiempo de compilación en vez de + tiempo de ejecución. Esto permite hacer algunos cálculos que no cambian de + ejecución en ejecución al momento de compilar, mejorando el rendimiento + o permitiendo formas avanzadas de meta-programación. Esta característica se + vuelve particularmente útil al combinarse con *string mixins*. Ejemplo:: @@ -359,12 +357,12 @@ Cantidad de parámetros variables para *templates*: Esta característica es vital para evitar la duplicación de código. -*Mixins*, incluyendo *string mixins*: +*Mixins*, incluyendo *string mixins* la palabra *mixin* tiene significados distintos en varios lenguajes de programación. En D_ *mixin* significa tomar una secuencia arbitraria de declaraciones e insertarla en el contexto (*scope*) actual. Esto puede - realizarse a nivel global, en clases, estructuras o funciones. Esto - sirve como un mecanismo para evitar duplicación de código que puede ser + realizarse a nivel global, en clases, estructuras o funciones. Esto sirve + como un mecanismo para evitar duplicación de código que puede ser introducida por la falta de herencia múltiple. Ejemplo:: @@ -385,10 +383,9 @@ Cantidad de parámetros variables para *templates*: *String mixin* se refiere a la capacidad de *incrustar* un *string* que contenga un fragmento de código en un programa como si este fragmento - hubiera sido escrito en el código fuente directamente por el - programador. Esto permite hacer manipulaciones arbitrariamente - complejas en combinación con funciones ejecutadas en tiempo de - compilación. + hubiera sido escrito en el código fuente directamente por el programador. + Esto permite hacer manipulaciones arbitrariamente complejas en combinación + con funciones ejecutadas en tiempo de compilación. Ejemplo:: @@ -402,11 +399,9 @@ Cantidad de parámetros variables para *templates*: Más información en http://www.digitalmars.com/d/1.0/mixin.html -Expresiones ``is``: - las *expresiones ``is``* permiten la compilación condicional basada en - las características de un tipo. Esto se realiza en favor a una técnica - utilizada en C++ de realizar *pattern matching* sobre los parámetros de - las plantillas. +Expresiones ``is`` + las *expresiones ``is``* permiten la compilación condicional basada en las + características de un tipo. Ejemplo:: @@ -417,39 +412,38 @@ Expresiones ``is``: return T.init; } - Esto provee además una forma simple de reflexión en tiempo de - compilación. + Esto provee además una forma simple de reflexión en tiempo de compilación. Más información en http://www.digitalmars.com/d/1.0/expression.html#IsExpression -.. _ref_d_low_level: +.. _d_low_level: Programación de bajo nivel (*system programming*) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Por programación de bajo nivel nos referimos a la capacidad de un lenguaje -de manipular el hardware directamente, o al menos la memoria. C es -probablemente el lenguaje de bajo nivel más popular, seguido por C++. +Por programación de bajo nivel nos referimos a la capacidad de un lenguaje de +manipular el hardware directamente, o al menos la memoria. C es probablemente +el lenguaje de bajo nivel más popular, seguido por C++. D_ presenta muchas características de bajo nivel: -Compila a código de máquina nativo: - no es interpretado ni necesita una máquina virtual como otros lenguajes - de más alto nivel como Java_, `C#`_, Python_, etc. +Compila a código de máquina nativo + no es interpretado ni necesita una máquina virtual como otros lenguajes de + más alto nivel como Java_, `C#`_, Python_, etc. -Provee acceso a *assembly*: +Provee acceso a *assembly* por lo tanto, acceso directo al *hardware* y la posibilidad de utilizar cualquier característica de éste que no esté disponible en el lenguaje. - Una ventaja sobre C y C++ es que el lenguaje *assembly* utilizado dentro - de D_ está especificado, por lo que se puede mantener la portabilidad - entre compiladores incluso cuando se utiliza *assembly* (mientras que no - se cambie de arquitectura, por supuesto). + Una ventaja sobre C y C++ es que el lenguaje *assembly* utilizado dentro de + D_ está especificado, por lo que se puede mantener la portabilidad entre + compiladores incluso cuando se utiliza *assembly* (mientras que no se + cambie de arquitectura, por supuesto). -``goto``: +``goto`` al igual que C y C++, D_ provee la flexibilidad del uso de ``goto``. Compatibilidad con C @@ -457,26 +451,28 @@ Compatibilidad con C permite enlazar archivos objeto estándar de C y D_ en un mismo programa. Además permite interoperar con C a través de ``extern (C)``. + .. [#abi] Interfaz de Aplicación Binaria (del inglés *Application Binary + Interface*). + Ejemplo:: extern (C) printf(const char* format, ...); printf("3 + 5 == %d\n", 3 + 5); // llama al printf de C -Manejo de memoria explícito: - permite alocar estructuras en el *stack* o en el *heap*, haciendo uso de +Manejo de memoria explícito + permite asignar estructuras en el *stack* o en el *heap*, haciendo uso de los servicios del sistema operativo o la biblioteca estándar de C. -Objetos y arreglos *livianos*: +Objetos y arreglos *livianos* por objetos *livianos* se entiende no-polimórficos. Es decir, un - agrupamiento de variables análogo al ``struct`` de C, sin tabla virtual - ni otro tipo de *overhead*. Los arreglos *livianos* son arreglos - estáticos como en C, cuyo tamaño es fijo, también sin ningún tipo de - *overhead* como C. Además puede alocarse un arreglo dinámicamente usando - ``malloc()`` y utilizar el operador ``[]`` para accederlo. + agrupamiento de variables análogo al ``struct`` de C, sin tabla virtual ni + otro tipo de *overhead*. Los arreglos *livianos* son arreglos estáticos + como en C, cuyo tamaño es fijo, también sin ningún tipo de *overhead* como + C. Además puede asignarse un arreglo dinámicamente usando ``malloc()`` + y utilizar el operador ``[]`` para accederlo. - Esto también permite interoperar con C, ya que pueden definirse - ``structs`` y arreglos que pueden ser intercambiados con dicho lenguaje - sin problemas. + Esto también permite interoperar con C, ya que pueden definirse ``structs`` + y arreglos que pueden ser intercambiados con dicho lenguaje sin problemas. Ejemplo:: @@ -496,16 +492,16 @@ Objetos y arreglos *livianos*: timeval tv; gettimeofday(&tv, null); -Rendimiento: - la :ref:`ref_d_generic` permite realizar muchas optimizaciones ya que se - resuelve en tiempo de compilación y por lo tanto aumentando la - *performance* en la ejecución. +Rendimiento + la :ref:`d_generic` permite realizar muchas optimizaciones ya que se + resuelve en tiempo de compilación y por lo tanto aumenta el rendimiento en + la ejecución. -Número de punto flotante de 80 bits: +Número de punto flotante de 80 bits El tipo ``real`` de D_ tiene precisión de 80 bits si la plataforma lo soporta (por ejemplo en i386). -Control de alineación de miembros de una estructura: +Control de alineación de miembros de una estructura Mediante ``align`` se puede especificar la alineación a tener en una estructura. @@ -519,39 +515,35 @@ Control de alineación de miembros de una estructura: // paquete_de_red.sizeof == 3 -.. [#abi] Interfaz de Aplicación Binaria (del inglés *Application Binary - Interface*). - -.. _ref_d_high_level: +.. _d_high_level: Programación de alto nivel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Programa de alto nivel se refiere a construcciones más avanzadas que un -loop. Expresiones semánticamente más ricas que permiten mayor expresividad -al programador o le permiten focalizarse de mejora manera en los algoritmos -independizándose del *hardware* o de como funciona una computadora. Es -exactamente el opuesto a :ref:`ref_d_low_level`. +Programación de alto nivel se refiere a construcciones más avanzadas que una +sentencia para iterar; expresiones con una semántica más ricas que proveen de +mayor expresividad al programador o le permiten focalizarse de mejora manera +en los algoritmos independizándose del *hardware* o de como funciona una +computadora. Es exactamente el opuesto a :ref:`d_low_level`. -En general estas características tiene como efecto secundario una mejora de -la productividad de los programadores. D_ adopta herramientas de muchos -lenguajes de alto nivel, como Java_ y Python_, por ejemplo: +En general estas características tienen como efecto secundario una mejora de la +productividad de los programadores. D_ adopta herramientas de muchos lenguajes +de alto nivel, como Java_ y Python_, por ejemplo: -Manejo automático de memoria: +Manejo automático de memoria al igual que C/C++ y prácticamente cualquier lenguaje imperativo maneja automáticamente el *stack*, pero a diferencia de la mayoría de los - lenguajes de bajo nivel, D_ permite manejar el *heap* de manera - automática también a través de un *recolección de basura*. + lenguajes de bajo nivel, D_ permite manejar el *heap* de manera automática + también a través de un *recolector de basura*. -Sistema de paquetes y módulos (similar a Java_ o Python_): +Sistema de paquetes y módulos (similar a Java_ o Python_) un módulo es una unidad que agrupa clases, funciones y cualquier otra construcción de lenguaje. Un paquete es una agrupación de módulos. D_ asocia un módulo a un archivo fuente (y un archivo objeto cuando éste es - compilado) y un paquete a un directorio. A diferencia de C/C++ no - necesita de un preprocesador para incluir declaraciones de otros - *módulos* (en C/C++ no existe el concepto de módulo, solo de unidades de - compilación). + compilado) y un paquete a un directorio. A diferencia de C/C++ no necesita + de un preprocesador para incluir declaraciones de otros *módulos* (en C/C++ + no existe el concepto de módulo, solo de unidades de compilación). Ejemplo: @@ -574,29 +566,37 @@ Sistema de paquetes y módulos (similar a Java_ o Python_): b.f(); f(); // ejecuta b.f() -Funciones y delegados: - las funciones pueden ser sobrecargadas (funciones con el mismo nombre - pero distinta cantidad o tipo de parámetros), pueden especificarse - argumentos de entrada, salida o entrada/salida, argumentos por omisión - o argumentos evaluados de forma perezosa (*lazy*). Además pueden tener - una cantidad de argumentos variables pero manteniendo información de - tipos (más seguro que C/C++). +Funciones y delegados + las funciones pueden ser sobrecargadas (funciones con el mismo nombre pero + distinta cantidad o tipo de parámetros), pueden especificarse argumentos de + entrada, salida o entrada/salida, argumentos por omisión o argumentos + evaluados de forma perezosa (*lazy*). Además pueden tener una cantidad de + argumentos variables pero manteniendo información de tipos (más seguro que + C/C++). Los *delegados* son punteros a función con un contexto asociado. Este contexto puede ser un objeto (en cuyo caso la función es un método) o un *stack frame* (en cuyo caso la función es una función anidada). Además de esto los delegados son ciudadanos de primera clase - [#1stclasscity]_, disponiendo de forma literal (delegado anónimo), lo - que permite construcciones de alto nivel muy conveniente. Los argumentos - evaluados de forma perezosa no son más que un delegado que se ejecuta - solo cuando es necesario. + [#1stclasscity]_, disponiendo de forma literal (delegado anónimo), lo que + permite construcciones de alto nivel muy conveniente. Los argumentos + evaluados de forma perezosa no son más que un delegado que se ejecuta solo + cuando es necesario. + + .. [#1stclasscity] Por ciudadano de primera clase se entiende que se trata + de un tipo soportado por completo por el lenguaje, disponiendo de + expresiones literales anónimas, pudiendo ser almacenados en variables, + estructuras de datos, teniendo una identidad intrínseca, más allá de un + nombre dado, etc. En realidad los arreglos asociativos no pueden ser + expresados como literales anónimos pero sí tienen una sintaxis especial + soportada directamente por el lenguaje. Ejemplo:: bool buscar(T[] arreglo, T item, bool delegate(T x, T y) igual) { foreach (t, arreglo) - if (igual(t, elemento)) + if (igual(t, item)) return true; return false; } @@ -613,15 +613,14 @@ Funciones y delegados: } ); -Arreglos *dinámicos* y arreglos asociativos: +Arreglos *dinámicos* y arreglos asociativos los arreglos *dinámicos* son arreglos de longitud variable manejados automáticamente por el lenguaje (análogos al ``std::vector`` de C++). - Soportan concatenación (a través del operador ``~``), rebanado - o *slicing* (a través del operador ``[x..y]``) y chequeo de límites - (*bound checking*). + Soportan concatenación (a través del operador ``~``), rebanado o *slicing* + (a través del operador ``[x..y]``) y chequeo de límites (*bound checking*). - Los arreglos asociativos (también conocidos como *hashes* - o diccionarios) también son provistos por el lenguaje. + Los arreglos asociativos (también conocidos como *hashes* o diccionarios) + también son provistos por el lenguaje. Ambos son ciudadanos de primera clase, disponiendo de forma literal. @@ -633,11 +632,11 @@ Arreglos *dinámicos* y arreglos asociativos: int[string] agenda; agenda["Pepe"] = 5555_1234; -*Strings*: +*Strings* al igual que los delegados y arreglos dinámicos y asociativos, los - *strings* son ciudadanos de primera clase, teniendo forma literal - y siendo codificados en UTF-8/16/32. Son un caso particular de arreglo - dinámico y es posible utilizarlos en sentencias ``switch``/``case``. + *strings* son ciudadanos de primera clase, teniendo forma literal y siendo + codificados en UTF-8/16/32. Son un caso particular de arreglo dinámico y es + posible utilizarlos en sentencias ``switch``/``case``. Ejemplo:: @@ -650,13 +649,13 @@ Arreglos *dinámicos* y arreglos asociativos: s = ""; } -``typedef`` y ``alias``: +``typedef`` y ``alias`` el primero define un nuevo tipo basado en otro. A diferencia de C/C++ el - tipo original no puede ser implícitamente convertido al tipo nuevo - (excepto valores literales), pero la conversión es válida en el otro - sentido (similar a los ``enum`` en C++). Por el contrario, ``alias`` es - análogo al ``typedef`` de C/C++ y simplemente es una forma de referirse - al mismo tipo con un nombre distinto. + tipo original no puede ser implícitamente convertido al tipo nuevo (excepto + valores literales), pero la conversión es válida en el otro sentido + (similar a los ``enum`` en C++). Por el contrario, ``alias`` es análogo al + ``typedef`` de C/C++ y simplemente es una forma de referirse al mismo tipo + con un nombre distinto. Ejemplo:: @@ -670,15 +669,15 @@ Arreglos *dinámicos* y arreglos asociativos: un_alias a = t; foo(a); -Documentación embebida: - D_ provee un sistema de documentación embebida, análogo a lo que provee - Java_ o Python_ en menor medida. Hay comentarios especiales del código - que pueden ser utilizados para documentarlo de forma tal que luego el +Documentación embebida + D_ provee un sistema de documentación embebida, análogo a lo que proveen + Java_ o Python_ en menor medida. Hay comentarios especiales del código que + pueden ser utilizados para documentarlo de forma tal que luego el compilador pueda extraer esa información para generar un documento. Más información en http://www.digitalmars.com/d/1.0/ddoc.html -Números complejos: +Números complejos D_ soporta números complejos como ciudadanos de primera clase. Soporta forma literal de números imaginarios y complejos. @@ -688,14 +687,6 @@ Números complejos: float re = 1.0; cfloat c = re + im; // c == 1.0 + 5.0i -.. [#1stclasscity] Por ciudadano de primera clase se entiende que se - trata de un tipo soportado por completo por el lenguaje, disponiendo de - expresiones literales anónimas, pudiendo ser almacenados en variables, - estructuras de datos, teniendo una identidad intrínseca, más allá - de un nombre dado, etc. En realidad los arreglos asociativos no pueden - ser expresados como literales anónimos pero sí tienen una sintaxis - especial soportada directamente por el lenguaje. - Programación orientada a objetos @@ -706,15 +697,27 @@ actualidad a la hora de diseñar e implementar un programa. D_ provee muchas herramientas para soportar este paradigma de forma confiable. Entre las características más salientes se encuentran: -Objetos *pesados*: +Objetos *pesados* objetos polimórficos como los de cualquier lenguaje con orientación real - a objetos. Estos objetos poseen una tabla virtual para *dispatch* - dinámico, todos los métodos son virtuales a menos que se indique lo - contrario y tienen semántica de referencia [#drefsem]_. Estos objetos - tienen un *overhead* comparados a los objetos *livianos* pero aseguran - una semántica segura para trabajar con orientación a objetos, evitando - problemas con los que se enfrenta C++ (como *slicing* [#dslicing]_) - debido a que permite semántica por valor [#dvalsem]_. + a objetos. Estos objetos poseen una tabla virtual para despacho dinámico, + todos los métodos son virtuales a menos que se indique lo contrario + y tienen semántica de referencia [#drefsem]_. Estos objetos tienen un + *overhead* comparados a los objetos *livianos* pero aseguran una semántica + segura para trabajar con orientación a objetos, evitando problemas con los + que se enfrenta C++ (como *slicing* [#dslicing]_) debido a que permite + semántica por valor [#dvalsem]_. + + .. [#drefsem] Semántica de referencia significa que el tipo es tratado como + si fuera un puntero. Nunca se hacen copias del objeto, siempre se pasa + por referencia. + .. [#dslicing] Este problema se da en C++ cuando se pasa una clase derivada + a una función que acepta una clase base por valor como parámetro. Al + realizarse una copia de la clase con el constructor de copia de la clase + base, se pierden (o *rebanan*) los atributos de la clase derivada, y la + información de tipos en tiempo de ejecución (*RTTI*). + .. [#dvalsem] Semántica de valor significa que el tipo es tratado como si + fuera un valor concreto. En general se pasa por valor y se hacen copias + a menos que se utilice explícitamente un puntero. D_ además soporta tipos de retorno covariantes para funciones virtuales. Esto significa que una función sobreescrita por una clase derivada puede @@ -736,22 +739,22 @@ Objetos *pesados*: Más información en http://www.digitalmars.com/d/1.0/function.html -Interfaces: +Interfaces D_ no soporta herencia múltiple pero sí interfaces. Una interfaz es - básicamente una tabla virtual, una definición de métodos virtuales que - debe proveer una clase. Las interfaces no proveen una implementación de - dichos métodos, ni pueden tener atributos. Esto simplifica mucho el - lenguaje y no se pierde flexibilidad porque puede conseguirse el mismo - efecto de tener herencia múltiple a través de interfaces y *mixins* para - proveer una implementación o atributos en común a varias clases que - implementan la misma interfaz. - -Sobrecarga de operadores: + básicamente una tabla virtual, una definición de métodos virtuales que debe + proveer una clase. Las interfaces no proveen una implementación de dichos + métodos, ni pueden tener atributos. Esto simplifica mucho el lenguaje y no + se pierde flexibilidad porque puede conseguirse el mismo efecto de tener + herencia múltiple a través de interfaces y *mixins* para proveer una + implementación o atributos en común a varias clases que implementan la + misma interfaz. + +Sobrecarga de operadores la sobrecarga de operadores permite que un objeto tenga una sintaxis similar a un tipo de dato nativo. Esto es muy importante además para la programación genérica. -Clases anidadas: +Clases anidadas al igual que C (con respecto a ``struct``) y C++, pueden anidarse clases dentro de clases. D_ sin embargo provee la posibilidad de acceder a atributos de la instancia exterior desde la anidada. @@ -767,11 +770,10 @@ Clases anidadas: } } - Esto tiene un pequeño *overhead* ya que la clase ``Anidada`` debe - guardar un puntero a la clase ``Exterior``. Si no se necesita este - comportamiento es posible evitar este *overhead* utilizando ``static``, - en cuyo caso solo puede acceder a atributos estáticos de la clase - ``Exterior``. + Esto tiene un pequeño *overhead* ya que la clase ``Anidada`` debe guardar + un puntero a la clase ``Exterior``. Si no se necesita este comportamiento + es posible evitar este *overhead* utilizando ``static``, en cuyo caso solo + puede acceder a atributos estáticos de la clase ``Exterior``. Ejemplo:: @@ -787,7 +789,7 @@ Clases anidadas: } -Propiedades (*properties*): +Propiedades (*properties*) en D_ se refiere a funciones miembro que pueden ser tratadas sintácticamente como campos de esa clase/estructura. @@ -805,25 +807,35 @@ Propiedades (*properties*): Además tipos nativos, clases, estructuras y expresiones tienen *properties* predefinidos, por ejemplo: - ``sizeof``: + ``sizeof`` tamaño ocupado en memoria (ejemplo: ``int.sizeof`` -> 4). - ``init``: + ``init`` valor de inicialización por omisión (ejemplo: ``float.init`` -> *NaN* [#dnan]_). - ``stringof``: - representación textual del tipo (ejemplo: ``(1+2).stringof`` -> ``"1 - + 2"``). + .. [#dnan] Del inglés *Not A Number*, es un valor especial que indica que + estamos ante un valor inválido. - ``mangleof``: + ``stringof`` + representación textual del símbolo o expresión (ejemplo: + ``(1+2).stringof`` -> ``"1 + 2"``). + + ``mangleof`` representación textual del tipo *mutilado* [#dmangle]_. + .. [#dmangle] *Name mangling* es el nombre dado comunmente a una técnica + necesaria para poder sobrecargar nombres de símbolos. Consiste en + codificar los nombres de las funciones tomando como entrada el nombre de + la función y la cantidad y tipo de parámetros, asegurando que dos + funciones con el mismo nombre pero distintos parámetros (sobrecargada) + tengan nombres distintos. + ``alignof`` alineación de una estructura o tipo. - Estos son solo los *properties* predefinidos para todos los tipos, pero - hay una cantidad considerable de *properties* extra para cada tipo. + Estos son solo los *properties* predefinidos para todos los tipos, pero hay + una cantidad considerable de *properties* extra para cada tipo. Más información sobre *properties* de clases en http://www.digitalmars.com/d/1.0/property.html#classproperties y sobre @@ -831,68 +843,49 @@ Propiedades (*properties*): http://www.digitalmars.com/d/1.0/property.html -.. [#drefsem] Semántica de referencia significa que el tipo es tratado como - si fuera un puntero. Nunca se hacen copias del objeto, siempre se pasa - por referencia. -.. [#dslicing] Este problema se da en C++ cuando se pasa una clase derivada - a una función que acepta una clase base por valor como parámetro. Al - realizarse una copia de la clase con el constructor de copia de la clase - base, se pierden (o *rebanan*) los atributos de la clase derivada, y la - información de tipos en tiempo de ejecución (*RTTI*). -.. [#dvalsem] Semántica de valor significa que el tipo es tratado como - si fuera un valor concreto. En general se pasa por valor y se hacen - copias a menos que se utilice explícitamente un puntero. -.. [#dnan] Del inglés *Not A Number*, es un valor especial que indica que - estamos ante un valor inválido. -.. [#dmangle] *Name mangling* es el nombre dado comunmente a una técnica - necesaria para poder sobrecargar nombres de símbolos. Consiste en - codificar los nombres de las funciones tomando como entrada el nombre de - la función y la cantidad y tipo de parámetros, asegurando que dos - funciones con el mismo nombre pero distintos parámetros (sobrecargada) - tengan nombres distintos. +.. _d_dbc: Programación confiable ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Programación confiable se refiere a las capacidades o facilidades que -provee el lenguaje para evitar fallas de manera temprano (o la capacidad de -evitar que ciertas fallas puedan existir directamente). D_ presta -particular atención a esto y provee las siguientes herramientas: +Programación confiable se refiere a las capacidades o facilidades que provee +el lenguaje para evitar fallas de manera temprana (o la capacidad de evitar +que ciertas fallas puedan existir directamente). D_ presta particular atención +a esto y provee las siguientes herramientas: -Excepciones: - D_ soporta excepciones de manera similar a Java_: provee ``try``, - ``catch`` y ``finally``. Esto permite que los errores difícilmente pasen +Excepciones + D_ soporta excepciones de manera similar a Java_: provee ``try``, ``catch`` + y ``finally``. Esto permite que los errores difícilmente pasen silenciosamente sin ser detectados. -``assert``: - es una condición que debe cumplirse siempre en un programa, como un - chequeo de integridad. Esto es muy utilizado en C/C++, donde - ``assert()`` es una *macro* que solo se compila cuando la *macro* - ``NDEBUG`` no está definida. Esto permite eliminar los chequeos de - integridad del programa, que pueden ser costosos, para versiones que se - suponen estables. +``assert`` + es una condición que debe cumplirse siempre en un programa, como un chequeo + de integridad. Esto es muy utilizado en C/C++, donde ``assert()`` es una + *macro* que solo se compila cuando la *macro* ``NDEBUG`` no está definida. + Esto permite eliminar los chequeos de integridad del programa, que pueden + ser costosos, para versiones que se suponen estables. D_ lleva este concepto más allá y hace al ``assert`` parte del lenguaje. - Si una verificación no se cumple, lanza una excepción. El ``assert`` no - es compilado cuando se utiliza una opción del compilador. + Si una verificación no se cumple, lanza una excepción. El ``assert`` no es + compilado cuando se utiliza una opción del compilador. Ejemplo:: File f = open("archivo"); assert (f.ok()); -Diseño por contrato: - el diseño por contrato es un concepto introducido por el lenguaje - Eiffel_ a mediados/finales de los '80. Se trata de incorporar en el - lenguaje las herramientas para poder aplicar verificaciones formales - a las interfaces de los programas. +Diseño por contrato + el diseño por contrato es un concepto introducido por el lenguaje Eiffel_ + a mediados/finales de los '80. Se trata de incorporar en el lenguaje las + herramientas para poder aplicar verificaciones formales a las interfaces de + los programas. D_ implementa las siguientes formas de diseño por contrato (todas se - ejecutan siempre y cuando no se compile en modo *release*, de manera de - no sacrificar *performance* cuando es necesario): + ejecutan siempre y cuando no se compile en modo *release*, de manera de no + sacrificar rendimiento cuando es necesario): - Pre y post condiciones: + Pre y post condiciones Ejemplo:: double raiz_cuadrada(double x) @@ -912,12 +905,12 @@ Diseño por contrato: // implementación } - Invariantes de representación: - La invariante de representación es un método de una clase - o estructura que es verificada cuando se completa su construcción, - antes de la destrucción, antes y después de ejecutar cualquier - función miembro pública y cuando se lo requiere de forma explícita - utilizando ``assert``. + Invariantes de representación + La invariante de representación es un método de una clase o estructura + que es verificada cuando se completa su construcción, antes de la + destrucción, antes y después de ejecutar cualquier función miembro + pública y cuando se lo requiere de forma explícita utilizando + ``assert``. Ejemplo:: @@ -932,7 +925,7 @@ Diseño por contrato: Más información en http://www.digitalmars.com/d/1.0/dbc.html -Pruebas unitarias: +Pruebas unitarias es posible incluir pequeñas pruebas unitarias en el lenguaje. Éstas son ejecutadas (cuando no se compila en modo *release*) al comenzar el programa, antes de que la función ``main()``. @@ -946,41 +939,41 @@ Pruebas unitarias: assert (fecha); } -Orden de construcción estática: +Orden de construcción estática a diferencia de C++, D_ garantiza el orden de inicialización de los módulos. Si bien en C++ no hay módulos si no unidades de compilación, es posible que se ejecute código antes del ``main()`` en C++, si hay, por - ejemplo, instancias globales con un constructor definido. C++ no - garantiza un orden de inicialización, lo que trae muchos problemas. En - D_ se define el orden de inicialización y es el mismo orden en que el - usuario importa los módulos. + ejemplo, instancias globales con un constructor definido. C++ no garantiza + un orden de inicialización, lo que trae muchos problemas. En D_ se define + el orden de inicialización y es el mismo orden en que el usuario importa + los módulos. -Inicialización garantizada: +Inicialización garantizada todas las variables son inicializadas por el lenguaje (a menos que el usuario pida explícitamente que no lo sean). Siempre que sea posible se - elijen valores de inicialización que permitan saber al programador que - la variable no fue inicializada explícitamente, de manera de poder - detectar errores de manera temprana. + elijen valores de inicialización que permitan saber al programador que la + variable no fue inicializada explícitamente, de manera de poder detectar + errores de manera temprana. Ejemplo:: - double d; // inicializado a NaN - int x; // inicializado a 0 - Fecha f; // inicializado a null - byte[5] a; // inicializados todos los valores a 0 + double d; // inicializado a NaN + int x; // inicializado a 0 + Fecha f; // inicializado a null + byte[5] a; // inicializados todos los valores a 0 long l = void; // NO inicializado (explícitamente) -*RAII* (*Resource Adquisition Is Initialization*): - es una técnica muy utilizada en C++ que consiste en reservar recursos - por medio de la construcción de un objeto y liberarlos cuando se libera - éste. Al llamarse al destructor de manera automática cuando se sale del - *scope*, se asegura que el recurso será liberado también. +*RAII* (*Resource Adquisition Is Initialization*) + es una técnica muy utilizada en C++ que consiste en reservar recursos por + medio de la construcción de un objeto y liberarlos cuando se libera éste. + Al llamarse al destructor de manera automática cuando se sale del *scope*, + se asegura que el recurso será liberado también. Esta técnica es la base para desarrollar código seguro en cuanto a excepciones (*exception-safe*) [SUTT99]_. - En D_ no es tan común utilizar *RAII* dada la existencia del recolector - de basura (en la mayoría de los casos el recurso a administrar es + En D_ no es tan común utilizar *RAII* dada la existencia del recolector de + basura (en la mayoría de los casos el recurso a administrar es sencillamente memoria). Sin embargo en los casos en donde es necesario, puede utilizarse *RAII* mediante la utilización de la palabra reservada ``scope``, que limita la vida de un objeto un bloque de código. @@ -996,42 +989,41 @@ Inicialización garantizada: // uso de archivo } // en este punto se llama al destructor de archivo -Guardias de bloque (*scope guards*): - además de poder limitar la vida de una instancia a un *scope*, es - posible especificar un bloque de código arbitrario a ejecutar al - abandonar un *scope*, ya sea cuando se sale del *scope* normalmente - o por una falla. +Guardias de bloque (*scope guards*) + además de poder limitar la vida de una instancia a un *scope*, es posible + especificar un bloque de código arbitrario a ejecutar al abandonar un + *scope*, ya sea cuando se sale del *scope* normalmente o por una falla. Ejemplo:: int f(Lock lock) { lock.lock(); scope (exit) - lock.unlock(); // ejecutado siempre que salga de f() + lock.unlock(); // ejecutado siempre que salga de f() auto trans = new Transaccion; scope (success) - trans.commit(); // ejecutado si sale con "return" + trans.commit(); // ejecutado si sale con "return" scope (failure) - trans.rollback(); // ejecutado si sale por una excepción + trans.rollback(); // ejecutado si sale por una excepción if (condicion) - throw Exception("error"); // ejecuta lock.unlock() y trans.rollback() + throw Exception("error"); // lock.unlock() y trans.rollback() else if (otra_condicion) - return 5; // ejecuta lock.unlock() y trans.commit() - return 0; // ejecuta lock.unlock() y trans.commit() + return 5; // lock.unlock() y trans.commit() + return 0; // lock.unlock() y trans.commit() } - Esta es una nueva forma de poder escribir código *exception-safe*, - aunque el programador debe tener un poco más de cuidado de especificar - las acciones a ejecutar al finalizar el *scope*. + Esta es una nueva forma de poder escribir código *exception-safe*, aunque + el programador debe tener un poco más de cuidado de especificar las + acciones a ejecutar al finalizar el *scope*. -Primitivas de sincronización de hilos: +Primitivas de sincronización de hilos la programación multi-hilo está directamente soportada por el lenguaje, - y se provee una primitiva de sincronización al igual que Java_. La - palabra reservada ``synchronized`` puede aparecer como modificador de - métodos (en cuyo caso se utiliza un *lock* por clase para sincronizar) - o como una sentencia, en cuyo caso se crea un *lock* global por cada - bloque ``synchronized`` a menos que se especifique sobre qué objeto - realizar la sincronización. Por ejemplo:: + y se provee una primitiva de sincronización al igual que Java_. La palabra + reservada ``synchronized`` puede aparecer como modificador de métodos (en + cuyo caso se utiliza un *lock* por clase para sincronizar) o como una + sentencia, en cuyo caso se crea un *lock* global por cada bloque + ``synchronized`` a menos que se especifique sobre qué objeto realizar la + sincronización. Por ejemplo:: class Foo { synchronized void bar() { /* cuerpo */ } @@ -1054,53 +1046,68 @@ y LDC_. DMD_ es el compilador de referencia, escrito por `Walter Bright`_. El *front-end* [#frontend]_ de este compilador ha sido liberado bajo licencia -Artistic_/GPL_ y es utilizado por los otros dos compiladores, por lo -tanto en realidad hay solo un compilador disponible con 3 *back-ends* -[#backend]_ diferentes. +Artistic_/GPL_ y es utilizado por los otros dos compiladores, por lo tanto en +realidad hay solo un compilador disponible con 3 *back-ends* [#backend]_ +diferentes. -Con `DMD 1.041`__ se publicó el código fuente completo del compilador, -pero con una licencia muy restrictiva para uso personal, por lo que el -único efecto logrado por esto es que la gente pueda mandar parches -o correcciones del compilador pero no lo convierte en `Software Libre`_, -siendo el único de los 3 compiladores que no tiene esta característica. +.. [#frontend] *Front-end* es la parte del compilador encargada de hacer el + análisis léxico, sintáctico y semántico del código fuente, generando una + representación intermedia que luego el *back-end* convierte a código de + máquina. + +.. [#backend] El *back-end* es la parte del compilador encargada de convertir + la representación intermedia generada por el *front-end* a código de + máquina. + +Con `DMD 1.041`__ se publicó el código fuente completo del compilador, pero +con una licencia muy restrictiva para uso personal, por lo que el único efecto +logrado por esto es que la gente pueda mandar parches o correcciones del +compilador pero no lo convierte en `Software Libre`_, siendo el único de los +3 compiladores que no tiene esta característica. __ http://www.digitalmars.com/d/1.0/changelog.html#new1_041 El compilador GDC_ es el *front-end* de DMD_ utilizando al compilador GCC_ -como *back-end*. Fue un muy buen compilador pero en la actualidad está -abandonado. No hay un *release* desde agosto de 2007 y no hay -actualizaciones serias del código desde mediados de 2008, por lo que no -parece haber muchas probabilidades de que se siga manteniendo. - -LDC_ es lo opuesto; un compilador joven, nacido a mediados de 2007 (aunque -vio la luz un año después aproximadamente), su primer *release* fue -a principios de 2009 y tuvo un crecimiento excepcional. En la actualidad -inclusive pasa más pruebas de estrés que el compilador de referencia DMD_. -Como *back-end* utiliza LLVM_, otro proyecto joven y con una tasa de -crecimiento muy alta. - -Además de estos compiladores hay varios otros experimentales, pero ninguno -de ellos de calidad suficiente todavía. Por ejemplo hay un compilador -experimental que emite *CIL* (*Common Intermediate Language*), el -*bytecode* de `.NET`_, llamado DNet_. También hay un *fron-end* escrito en -D_, llamado Dil_ +como *back-end*. Fue un muy buen compilador pero estuvo abandonado por casi +tres años. A mediados de este año recibió un nuevo impulso y de a poco se está +poniendo al día con los *front-ends* actuales de DMD_ 1.0 y 2.0, aunque la +versión 2.0 viene bastante más rezagada y todavía no es una alternativa viable +a DMD_. + +LDC_ sufrió una suerte similar, es un compilador joven que utiliza como +*back-end* a LLVM_ (una infraestructura modera para construir compiladores), +nacido a mediados de 2007 como un proyecto personal y privado de Tomas +Lindquist Olsen, que estuvo trabajando de forma privada en el proyecto hasta +mediados de 2008, momento en que decide publicar el código mediante una +licencia libre. Para ese entonces el compilador era todavía inestable +y faltaban implementar varias cosas, pero el estado era lo suficientemente +bueno como para captar varios colaboradores muy capaces, como `Christian +Kamm`_ y Frits Van Bommel que rápidamente se convirtieron en parte fundamental +del proyecto. El primer *release* (0.9) de una versión relativamente completa +y estable fue a principios de 2009 que fue seguido por la versión 0.9.1 que +como puntos más salientes agregó soporte para x86-64 y assembly embebido. El +compilador tuvo un crecimiento excepcional pero estuvo muy inactivo por algún +tiempo y, si bien sigue siendo mantenido, en general los nuevos *front-end* de +DMD_ llevan tiempo de integrar y no está al día con el *back-end* de LLVM_ +(por ejemplo desde que se actualizó para utilizar LLVM_ 2.7 que perdió la +capacidad de generar símbolos de depuración). + +Además de estos compiladores hay varios otros experimentales, pero ninguno de +ellos de calidad suficiente todavía. Por ejemplo hay un compilador +experimental que emite *CIL* (*Common Intermediate Language*), el *bytecode* +de `.NET`_, llamado DNet_. También hay un *front-end* escrito en D_, llamado +Dil_. Originalmente, dado que GDC_ estaba siendo mantenido y que LDC_ no existía, -este trabajo iba a ser realizado utilizando GDC_ como compilador, dado que -al ser `Software Libre`_ podía ser modificado de ser necesario. Finalmente, -gracias a la excepcional tasa de crecimiento de LDC_ y al abandono de GDC_ -se terminó desarrollando el trabajo utilizando LDC_. - - -.. [#frontend] *Front-end* es la parte del compilador encargada de hacer el - análisis léxico, sintáctico y semántico del código fuente, generando una - representación intermedia que luego el *back-end* convierte a código de - máquina. -.. [#backend] El *back-end* es la parte del compilador encargada de - convertir la representación intermedia generada por el *front-end* - a código de máquina. +este trabajo iba a ser realizado utilizando GDC_ como compilador, dado que al +ser `Software Libre`_ podía ser modificado de ser necesario. Pero finalmente, +dada la poca confiabilidad que presenta la continuidad del desarrollo de tanto +GDC_ como LDC_, y que el código de DMD_ está disponible en su totalidad +(aunque no sea `Software Libre`_ por completo), se optó por utilizar este +último, dado que es la implementación de referencia que fue más constantemente +mantenida y desarrollada. .. include:: links.rst -.. vim: set ts=3 sts=3 sw=3 et tw=78 : +.. vim: set ts=3 sts=3 sw=3 et tw=78 spelllang=es :