La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria.

Presentaciones similares


Presentación del tema: "Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria."— Transcripción de la presentación:

1 Lenguaje

2 Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria y recolección de basura. Características destacables. Problemas y controversias. Back tracking.

3

4 Historia del Lenguaje -Creado por Walter Brigth en Versiones 1.0 (2007) y 2.0 (2010). -Influencias C, C++, Java, Perl, Phyton y Ruby _ Compiladores DMD, GDC y LDC. Parece que la mayoría de los lenguajes de programación nuevos caen en 2 categorías: aquellos académicos con nuevos paradigmas radicales y aquellos de grandes corporaciones con el foco en el desarrollo rápido y web. Tal vez es hora de que nazca un nuevo lenguaje de la experiencia práctica implementando compiladores. Origen

5 Características -Paradigmas Multiparadigma, Orientado a objetos, Imperativo -Tipo de Dato Fuerte, Estático -Sintaxis tipo C Ejemplo: En C char s[8]; strcpy(s, "algo"); printf("string = '%s'\n", s);printf En D char[] s; s = "algo"; printf("string = '%.*s'\n", s); -Compatibilidad binaria.

6 A continuación se enumeran las principales características de D, agrupadas por unidades funcionales o paradigmas que soporta: Programación genérica y meta-programación Programación de bajo nivel (system programming) Programación de alto nivel Programación orientada a objetos Programación conable

7 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 reere 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:

8 Esta construcción es similar a la directiva del preprocesador de C/C++ #if, pero a diferencia de éste, el static if de D tiene acceso a todos los símbolos del compilador (constantes, tipos, variables, etc). Ejemplo:

9 Si no se especica un tipo al declarar una variable, se inere a partir del tipo de su valor de inicialización Ejemplo: Mediante el uso de typeof se puede solicitar el tipo de una expresión arbitraria Ejemplo:

10 Cualquier tipo de colección (arreglos estáticos y dinámicos, arreglos asociativos, clases, estructuras o delegados) puede ser iterada mediante la sentencia foreach Ejemplo:

11 Tanto clases como 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 polimorsmo en tiempo de compilación, y es la forma más básica de programación genérica. Ejemplo:

12 Además se pueden denir bloques redeclaraciones 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:

13 La utilidad más prominente de los bloques generalizados se da al acompañarse de mixins. Además las templates de D tienen las siguientes características destacables: Instanciación implícita de funciones generalizadas El lenguaje es capaz rededucir los parámetros siempre que no hayan ambigüedades. Ejemplo:

14 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 reere 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 especicar el tipo al que apunta dicho puntero o el tipo almacenado por el arreglo. Ejemplo de especialización:

15 Ejemplo de especialización parcial:

16 Tipos, valores (incluyendo strings) y templates como parámetros Este 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 metaprogramas. Ejemplo:

17 Cantidad de parámetros variables para templates Esta característica permite implementar tuplas y otros algoritmos que inherentemente deben tomar una cantidad variable de parámetros en tiempo de compilación. Ejemplo:

18 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 el rendimiento o permitiendo formas avanzadas de meta-programación. Esta característica se vuelve particularmente útil al combinarse con string mixins. Ejemplo: Esta característica es muy importante para evitar la duplicación de código.

19 La palabra mixin tiene signicados distintos en varios lenguajes de programación. En D mixin signica 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 introducida por la falta de herencia múltiple Ejemplo:

20 String mixin se reere 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 elcódigo fuente directamente por el programador. Esto permite hacer manipulaciones arbitrariamente complejas en combinación con funciones ejecutadas en tiempo de compilación. Ejemplo:

21 Las expresiones is permiten la compilación condicional basada en las características de un tipo Ejemplo: Esto provee además una forma simple de reexión en tiempo de compilación.

22 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 Los programas generados por D no son interpretados ni necesitan una máquina virtual como otros lenguajes de más alto nivel como Java, C#, Python, etc.

23 Provee 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á especicado, 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 Al igual que C y C++, D provee la exibilidad del uso de goto.

24 Soporta todos los tipos de C y es ABI (Interfaz de Aplicación Binaria) compatible con éste. Esto 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) Ejemplo:

25 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 Por objetos livianos se entiende no-polimórcos. 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 jo, 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 denirse structs y arreglos que pueden ser intercambiados con dicho lenguaje sin problemas.

26 Ejemplo:

27 La Programación genérica y meta-programación permite realizar muchas optimizaciones ya que se resuelven en tiempo de compilación y por lo tanto aumenta el rendimiento en la ejecución. Número de punto otante de 80 bits El tipo real de D tiene precisión de 80 bits si la plataforma lo soporta (por ejemplo en i386).

28 Mediante align se puede especicar la alineación a tener en una estructura. Ejemplo:

29 Programación de alto nivel se reere 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 mejor manera en los algoritmos independizándose del hardware o de cómo funciona una computadora. Es exactamente el opuesto a Programación de bajo nivel (system programming). 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:

30 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 recolector de basura.

31 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).

32 Ejemplo: a.d: b.d: c.d:

33 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). 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. Ejemplo:

34 Al igual que los delegados y arreglos dinámicos y asociativos, los strings son ciudadanos de primera clase, teniendo forma literal y siendo codicados en UTF-8/16/32. Son un caso particular de arreglo dinámico y es posible utilizarlos en sentencias switch/case. Ejemplo:

35 El primero dene 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. Ejemplo:

36 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.

37 D soporta números complejos como ciudadanos de primera clase. Soporta forma literal de números imaginarios y complejos. Ejemplo:

38 La orientación a objetos es probablemente el paradigma más utilizado en la actualidad a la hora de diseñar e implementar un programa. D provee muchas herramientas para soportar este paradigma de forma conable. Entre las características más salientes se encuentran:

39 Objetos polimórcos como los de cualquier lenguaje con orientación real 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 (el tipo es tratado como si fuera un puntero. Nunca se hacen copias del objeto, siempre se pasa por referencia).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. 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).

40 Esto sucede porque permite semántica por valor (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 retornar un tipo que sea derivado del tipo retornado por la función original sobreescrita. Ejemplo:

41 Declaración de una clase: class NombredelaClase { class NombredelaClase: Object { } class NombredelaClase { enum constante = 0.2; // Una constante static immutable nombreDefault = Una Clase"; // Algunas variables asignadas a cada objeto NombredelaClase string nombre = nombreDefault; uint width, height; static double metodo() { // Un método estático return constante; } void cambiarNombre(string otro) { // Un método nombre = otro; } final void tamañoCuadruple() { // Un método que no se delega width *= 2; height *= 2; }

42 D no soporta herencia múltiple pero sí interfaces. Una interfaz es básicamente una tabla virtual, una denició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 simplica mucho el lenguaje y no se pierde exibilidad 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

43 interface Observador { void notificar(Object dato); } interface ElementoVisual { void dibujar(); } interface Actor { void actuar(); } interface ObservadorActor : Observador, Actor { void setActivo(bool activo); } interface Visual : Actor, ElementoVisual { void animar(); } class Sprite : Visual, Observador, ObservadorActor { void dibujar() {... } void animar() {... } void actuar() {... } void setActivo(bool activo); void notificar(Object dato) {... } }

44 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.

45 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. Ejemplo:

46 Esto tiene un pequeño overhead ya que la clase Anidada debe guardar un puntero a la clase Exterior. Sino 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:

47 Programación conable se reere 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:

48 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. Ejemplo: try { throw new Exception("mensaje de error"); } catch(Exception e) { printf("capturada la excepción, mensaje: %.*s\n", e.msg); } finally { printf("este mensaje se mostrará siempre"); }

49 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á denida. 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 vericación no se cumple, lanza una excepción. El assert no es compilado cuando se utiliza una opción del compilador. Ejemplo:

50 El diseño por contrato es un concepto introducido por el lenguaje Eiffel a mediados/nales de los 80. Se trata de incorporar en el lenguaje las herramientas para poder aplicar vericaciones 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 sacricar rendimiento o cuando es necesario):

51 Ejemplo:

52 La invariante de representación es un método de una clase o estructura que es vericada 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:

53 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(). Ejemplo:

54 A diferencia de C++, D garantiza el orden de inicialización de los módulos. Si bien en C++ no hay módulos sino 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 denido. C++ no garantiza un orden de inicialización, lo que trae muchos problemas. En D se dene el orden de inicialización y es el mismo ordenen que el usuario importa los módulos.

55 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. Ejemplo:

56 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). 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 a un bloque de código.

57 Ejemplo:

58 Además de poder limitar la vida de una instancia a un scope, es posible especicar un bloque de código arbitrario a ejecutar al abandonar un scope, ya sea cuando se sale del scope normalmente o por una falla.

59 Ejemplo: Esta es una nueva forma de poder escribir código exception-safe, aunque el programador debe tener un poco más de cuidado de especicar las acciones a ejecutar al nalizar el scope.

60 La programación multi-hilo está directamente soportada por el lenguaje, y se provee una primitiva desincronización al igual que Java. La palabra reservada synchronized puede aparecer como modicador 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 especique sobre qué objeto realizar la sincronización.Por ejemplo: Es equivalente a:

61

62 Punto de entrada de un programa Función main() void main() {... } void main(char[][] args) {... } int main() {... } int main(char[][] args) {... }

63 Declaración anticipada innecesaria - Obligatorio en C y C++ - Innecesario en D (al igual que Java) Ejemplo de C: void llamaotra(int prueba) { funcionprimera( prueba ); // error, funcionprimera no está definida } void funcionprimera(int param) { return param; }

64 Retorno de valores de una funcion vRetorno funcion( … ) { … } Tipos destacables: autoDeteccion automatica de tipo refRetorno por referencia Donde vRetorno puede ser cualquier tipo valido del lenguaje

65 Pasaje de parámetros -Pasaje por valor (utilizado por defecto) -Punteros a variables (sintaxis de C) -Pasaje por referencia (utilizando modificador ref. ver ejemplo) void main( char[][] args ) { int a = 0; test_param(a); writefln( a ); // Resultado: a = 1 } // Modificador ref en parametro a void test_param ( ref int a ) { a++; }

66 Propiedades Indicada con el Reemplazo elegante a sets y gets No violan encapsulamiento struct S { int { int x() { return m_x; } int x(int newx) { return m_x = newx; } } void foo() { S s; s.x = 3; // Llama a s.x(int) bar(s.x); // Llama a bar(s.x()) }

67 Sobrecarga de funciones -Niveles de comparacion de argumentos: 1.Sin compatibilidad 2.Compatibilidad con conversiones implicitas 3.Compatibilidad con conversiones explicitas 4.Compatibilidad completa -Eleccion de funcion sobrecargada basada en argumentos -Preferencia de función mas especializada

68 Evaluación perezosa de un argumento de función No evalúa la expresión hasta que el resultado de esta sea requerido void log(lazy char[] dg) { if (logging) fwritefln(logfile, dg()); } void foo(int i) { log("Entering foo() with i set to " ~ toString(i)); }

69 Funciones Puras -Devuelve siempre el mismo resultado para un mismo conjunto de argumentos -No lee ni escribe valores mutables globales -No puede llamar a funciones no puras -Puede redefinir una función impura, pero una función impura no puede redefinir a una función pura -No puede realizar operaciones I/O

70 Delegados void foo( int a ) { void bar() { writefln( a ); } void delegate() dg; dg = &bar; call( dg ); } void call( void delegate() dg ) { dg(); } void main( char[][] args ) { foo( 100 ); } -Similares a los punteros a métodos C++ -Compuesto por referencia a objeto (this) y puntero a función -Scope en el nivel donde fue creado

71 Clausura - Implementada para ser utilizada con delegados - Persistencia del entorno local donde fue creado el delegado -Variables utilizadas en clausura son copiadas al heap de memoria (heap-based memory) - El resto de las variables permanece en el stack de la aplicación (Ver ejemplo clausura.d)

72

73 void void no contiene ningún dato. bit Un único bit que representa 0 o 1 (true o false). Se inicializa con un valor default false. bool (bool es un alias de bit) El tipo bool tiene el tamaño de 1 byte que solo puede tener como valor true ó false. Los unicos operadores que puede aceptar de tipo bool son: & | ^ &= |= ^= ! && || ?: character char ch; // unsigned 8 bit UTF-8 wchar wch; // unsigned 16 bit UTF-16 dchar dch; // unsigned 32 bit UTF-32

74 Integer byte b; // signed 8 bits [ ] short s; // signed 16 bits [ ] int i; // signed 32 [ ] long l; // signed 64 [-1.8e e19] cent c; // signed 128 [-1,7e ,7e+38] ubyte b // unsigned 8 bits [ ] ushort; uint; ulong; // unsigned 64 [ ] ucent; // unsigned 128 [0.. 3,4e+38]

75 Floatingpoint float f; // 32 bit floating point double d; // 64 bit floating point real r; // punto flotante mas grande que el hardware implementa ifloat if; // float imaginario idouble id; // double imaginario ireal ir; // real imaginario cfloat cf; // numero complejo con 2 variables flotantes cdouble cd; // double complejo creal cr; // real complejo

76 int[5] b; // B es un array de 5 ints (estático) int[] a; // Se creó un array a que puede contener integers (no estático) int* p; int[5] a; int[] b; p = a; // esto funciona como una referencia p = null; // esto destruye' la referencia b = a; // posible. //b = p; //imposible! b[0..2] = 5; // esto también es válido

77 En D, además de existir una biblioteca de plantillas de clase avanzadas (la DTL, actualmente en desarrollo) los arrays cuentan con una serie de características que los hacen mucho más prácticos y manejables que los de C/C++: Cuentan con comprobación de límites. Pueden redimensionarse dinámicamente cambiando su propiedad "length" o añadiendo al final con el operador "~=". Pueden concatenarse fácilmente dos o más arrays en uno sólo con el operador "~".

78 Concatenación con el operador ~ : Ejemplo 1: char[] a = "He"; char[] b = "o world!"; char[] d = "l"; char[] c = a ~ d ~ "l" ~ b; // c == "Hello world! Ejemplo 2: static int[] a = [1,2,3]; static int[] b = [2,3]; int[] c = a ~ b; // c es un array [1,2,3,2,3]

79 Permiten la especificación de subrangos dentro de un array. Por ejemplo, si quisiéramos los elementos 3, 4 y 5 de un array en un subarray podríamos hacer: subarray = miarray[3..5]. Esto además permite copiar de forma sencilla los arrays por valor con la siguiente notación: int array2[] = array1[]; Los rangos también permiten asignaciones automáticas a varios elementos de un array simultaneamente: array[2..6] = 0; Cuentan con propiedades útiles (como size para el tamaño, dup para crear un duplicado, reverse para invertir el orden de los elementos y sort para ordenarlos.)

80 Los arrays estáticos (en los que en la declaración indicamos el tamaño de cada dimensión como en int[3][4] matriz; se implementan como las matrices de fortran en lugar de como punteros a punteros; esto hace que sean mucho más eficientes a la hora de calcularlos. Los arrays dinámicos (int[ ][ ] matriz;) sin embargo sí que se implementan como en C, como punteros a punteros. Por lo tanto, si necesitamos hacer cálculos de matrices extremadamente rápidos es aconsejable usar los arrays estáticos. En general todas estas características hacen que los arrays en D se manejen de la forma más intuitiva.

81 Una consecuencia directa de estos arrays mejorados es que las cadenas nativas, a pesar de seguir siendo arrays de caracteres, son ahora infinítamente más manejables. Lo único que tenemos que tener en consideración es que los literales de cadena (caracteres entre comillas) son arrays inmutables, esto es, que no pueden ser modificadas y como D no deja asignar entre objetos mutables e inmutables sin hacer conversiones, no podemos asignar los literales de cadena a arrays de char si no los declaramos mutables. Ejemplos: char[] cadenaMutable; // Cadena es un array de caracteres mutable; char[] otraCadenaMutable; cadenaMutable = Hola!"; // ERROR: Hola!" como literal de cadena es inmutable y no podemos asignarlo a un mutable otraCadenaMutable = Hola!".dup // Correcto, dup crea una copia mutable del literal

82 Para asignar literales de cadena sin llamar a.dup podríamos declarar a los arrays de caracteres como invariantes: invariant(char)[] cadenaInmutable = hola!"; // Correcto, asignamos un inmutable a otro invariant(char)[] otraCadenaInmutable = cadenaMutable; // ERROR, asignando mutable a inmutable invariant(char)[] ultimaCadenaInmutable = cadenaMutable.idup; // Correcto, idup crea una copia inmutable Por practicidad, se ha creado un alias a invariant(char)[] llamado string, de modo que el ejemplo anterior quedaría como: string cadenaInmutable = "hola!"; // Correcto, asignamos un inmutable a otro string otraCadenaInmutable = cadenaMutable; // ERROR, asignando mutable a inmutable string ultimaCadenaInmutable = cadenaMutable.idup; // Correcto, idup crea una copia inmutable

83 Las cadenas al no ser más que arrays de char en D pueden tienen las mismas operaciones que éstos (y el mismo rendimiento): // Asignación cadena1 = cadena2; // Copia string cadena1 = cadena2.dup; // // Copia de subcadenas string cadena1 = Hola! Amigos!"; string cadena2 = cadena1[0..4]; // cadena2 = "Hola!" // Concatenación string cadena3 = cadena1 ~ cadena2; // Añadir al final string cadena4 = "Hola! "; cadena4 ~= Amigos!"; // Comparación if (cadena1 > cadena2)...

84

85 if ( /* expresión booleana */ ) sentencia; // Opcional: else sentencia;

86 switch( /* variable */ ) { // if ( variable == 0) case 0: sentencia; break; // if ( (variable == 1) || (variable == 2) || (variable == 3) || (variable == 4) ) case 1,2,3,4: sentencia; break; // if (! (std.string.strcmp(variable,"hello") || std.string.strcmp(variable,"world")) ) case "hello", "world": sentencia; break; // "else" default: sentencia; break; }

87 enum Estado { listo, ocupado, fallo } final switch (Estado) { case listo:... case ocupado:... case fallo... }

88 while ( /* expresión booleana */ ) sentencia; ó: while ( /* expresión booleana */ ) { sentencia1; sentencia2; //... }

89 do { statement; } while ( /* expresión booleana */ );

90 for ( /* initializer */ ; /* test */ ; /* increment */ ) statement;

91 import std.math, std.stdio; struct Point { double x, y; double norm() { return sqrt(x * x + y * y); } } void main() { Point p; int z; with (p) { x = 3; // Asigna a p.x p.y = 4; // Asigna a p explícitamente writeln(norm()); // Escribe p.norm, que es 5 z = 1; // z es visible }

92

93 -Manejo de memoria explícito, usando operadores new y delete, o bien las funciones malloc y free. Memoria manejada por un recolector de basura. Objetos específicos pueden ser finalizados al salir del ámbito. Ejemplo: (códigos equivalentes) C++ void pierdeaceite() { Obj *o = new Obj(); } //fuga de memoria al salir del scope Dvoid nopierdeaceite() { Obj o = new Obj(); } // el recolector libera la memoria

94 Recolección controlada, los programadores pueden agregar o excluir rangos de memoria de ser observados por el recolector, pueden pausar y reanudar el recolector (gc.disable(), gc.enable()) y forzar un ciclo de recolección generacional o de recolección completa. -Si se desactiva el recolector, las referencias a los objetos que se hagan con un new se seguirán contabilizando, por lo que al re-activar la recolección esos objetos serán igualmente gestionados (no hay necesidad de llamar a delete). -No genera conflicto con el recolector si se llamamos a delete.

95

96 La sobrecarga de operadores en D a veces son menos poderosas que las de C++. Un ejemplo es el opIndex, que sufre porque D no permite regresar referencias. Esto hace operaciones como obj[i]++; imposibles. La solución parcial de D es el operador opIndexAssign, que solo repara casos donde la expresión indexeada es solo un valor L como obj[i] = 5 pero no los casos originales.

97 La biblioteca estándar en D es llamada Phobos. Algunos miembros de la comunidad piensan que Phobos es demasiado simple y que posee numerosos problemas, por lo cual un reemplazo llamado Tango fue escrito. Sin embargo, Tango y Phobos son por el momento incompatibles debido a varias diferencias (soporte de hilos, recolector de basura, etc). La existencia de dos bibliotecas, ambas de uso elevado, puede llevar a problemas significativos donde algunos paquetes usan Phobos y otros usan Tango.

98 Bibliotecas compartidas ELF de Unix son soportadas hasta un punto usando el compilador GDC. En Windows, DLLs son soportadas y permiten a objetos recolectados por el recolector de basura de ser seguramente pasados a funciones de C, ya que el recolector de basura revisa el stack por punteros. Sin embargo, todavía hay limitaciones con DLLs en D incluyendo el hecho de que la información en tiempo de ejecución de clases definidas en la DLL es incompatible con esas definidas en el ejecutable, y que cualquier objeto creado desde la DLL debe ser finalizado antes de que la DLL sea descargada.

99 El lenguaje tiene tres distintos tipos de caracteres (char, wchar y dchar) y tres alias de string (string, wstring y dstring, que son arrays dinámicos). UTF-8, UTF-16 y UTF-32 representan las unidades de código y strings respectivamente. Por razones de rendimientos, dividir strings y la propiedad length operan en unidades de código (caracteres) en lugar de puntos de código (algún valor numérico), que frecuentemente confunde a desarrolladores. Desde que UTF-8 y UTF-16 son codificaciones de caracteres de longitud variable, acceder por el indice de puntos de codigo no es posible sin el mantenimiento de tablas adicionales de búsqueda. El código que necesite rápido acceso a puntos de código debería convertir los strings a UTF-32 primero, o usar tablas de búsqueda. Sin embargo, esto es también sucede en otros lenguajes de programación que soportan Unicode, como Java y C# que usan UTF-16, por lo tanto, es necesario usar sustitutos para representar a algunos puntos de código.

100 Implementaciones en D -IDE Poseidón -Juegos - ABA Juegos (Titanion, Torus Troopers,Tumiki Fighters) -AREA2048 -Empire -QonkD -Yagé

101

102 Muchas Gracias!

103


Descargar ppt "Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria."

Presentaciones similares


Anuncios Google