105

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

Embed Size (px)

Citation preview

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

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

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

Historia del Lenguaje

-Creado por Walter Brigth en 1999- 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

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

CaracterísticasCaracterí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);

En D char[] s; s = "algo"; printf("string = '%.*s'\n", s);

-Compatibilidad binaria.

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

Características del lenguaje 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 confiable

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

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). D provee las siguientes herramientas para realizar programación genérica y meta-programación:

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

If estático (static if)

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:

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

Inferencia de tipos básica implícita y explícita (mediante typeof)

Si no se especifica un tipo al declarar una variable, se infiere a partir del tipo de su valor de inicializaciónEjemplo:

Mediante el uso de typeof se puede solicitar el tipo de una expresión arbitrariaEjemplo:

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

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

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

Templates

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

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

Templates

Además se pueden definir 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:

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

Templates

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 generalizadasEl lenguaje es capaz rededucir los parámetros siempre que no hayan ambigüedades.Ejemplo:

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

Templates

Especialización explícita y parcial de templatesLa 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:

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

Templates

Ejemplo de especialización parcial:

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

Templates

Tipos, valores (incluyendo strings) y templates como parámetrosEste 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:

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

Templates

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

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

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

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

Mixins, incluyendo string mixinsLa 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 introducida por la falta de herencia múltipleEjemplo:

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

Mixins, incluyendo string mixins

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

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

Expresiones is

Las expresiones ‘‘is‘‘ permiten la compilación condicional basada en las características de un tipoEjemplo:

Esto provee además una forma simple de reflexión en tiempo de compilación.

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

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

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

Assembly empotrado

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á 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).gotoAl igual que C y C++, D provee la flexibilidad del uso de goto.

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

Compatibilidad con C

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:

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

Manejo de memoria explícitoPermite 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 livianosPor 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 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.

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

Objetos y arreglos livianos

Ejemplo:

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

Rendimiento

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 flotante de 80 bits

El tipo real de D tiene precisión de 80 bits si la plataforma lo soporta (por ejemplo en i386).

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

Control de alineación de miembros de una estructura

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

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

Programación de alto nivel 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 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:

Page 30: Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo 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 recolector de basura.

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

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

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

Sistema de paquetes y módulos

Ejemplo:a.d:

b.d:

c.d:

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

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

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

Funciones y delegados

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 stackframe (en cuyo caso la función es una función anidada).Además de esto los delegados son ciudadanos de primera clase (se trata de un tipo soportado por completo por el lenguaje), 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.

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

Funciones y delegados

Ejemplo:

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

Arreglos dinámicos y arreglos asociativosLos 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:

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

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

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

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

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

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.

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

Números complejos

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

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

Programación orientada a objetos 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 confiable. Entre las características más salientes se encuentran:

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

Objetos pesados

Objetos polimórficos 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).

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

Objetos pesados

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:

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

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

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

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.

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

Clases

Declaración de una clase:

class NombredelaClase { //Variables

//Métodos}

Protección: private package public export

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

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

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

Clases anidadas

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:

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

Propiedades (properties)

En D se refiere a funciones miembro que pueden ser tratadas sintácticamente como campos de esa clase/estructura.Ejemplo:

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

Propiedades (properties)

Además tipos nativos, clases, estructuras y expresiones tienen properties predefinidos, por ejemplo:sizeof: Tamaño ocupado en memoria (ejemplo: int.sizeof ->4).Init: Valor de inicialización por omisión (ejemplo: float.init -> NaN) Not A Number (un valor inválido).stringof: Representación textual del símbolo o expresión (ejemplo: (1+2).stringof -> "1+2").mangleof: Representación textual del tipo mutilado (Name mangling es el nombre dado comúnmente a una técnica necesaria para poder sobrecargar nombres de símbolos).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.

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

Programación confiable

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:

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

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.

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

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

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

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 rendimiento ocuando es necesario):

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

Pre y postcondiciones

Ejemplo:

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

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:

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

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

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

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 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 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 ordenen que el usuario importa los módulos.

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

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

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

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

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

RAII (Resource Adquisition Is Initialization)

Ejemplo:

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

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.

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

Guardias de bloque (scope guards)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 especificar las acciones a ejecutar al finalizar el scope.

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

Primitivas de sincronización de hilos

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

Es equivalente a:

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

Punto de entrada de un programa

Funcion main()

void main() { ... }

void main(char[][] args) { ... }

int main() { ... }

int main(char[][] args) { ... }

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

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; }

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

Retorno de valores de una funcion

vRetorno funcion( … ) { … }

Tipos destacables: •auto Deteccion automatica de tipo•ref Retorno por referencia

Donde vRetorno puede ser cualquier tipo valido del lenguaje

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

Pasaje de parametros

• 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++;}

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

Propiedades

• Indicada con el atributo @property • Reemplazo elegante a sets y gets• No violan encapsulamiento

struct S{ int m_x; @property { 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())}

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

Sobrecarga de funciones

Niveles de comparacion de argumentos:

1.Sin compatibilidad2.Compatibilidad con conversiones implicitas3.Compatibilidad con conversiones explicitas4.Compatibilidad completa

Eleccion de funcion sobrecargada basada en argumentos

Preferencia de función mas especializada

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

Evaluacion ‘perezosa’ de un argumento de funcion

No evalua la expresion hasta que el resultado de estasea requerido

void log(lazy char[] dg){ if (logging)

fwritefln(logfile, dg());}

void foo(int i){ log("Entering foo() with i set to " ~ toString(i));}

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

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 redifinir una funcion impura,

pero una funcion impura no puede redefinir a una funcion pura• No puede realizar operaciones I/O

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

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 metodos C++• Compuesto por referencia a objeto (this) y puntero a funcion• Scope en el nivel donde fue creado

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

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

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

void Void does not contain any data.

bit A single bit represents zero or one (true or false).The default initialised value is 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

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

Integer

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

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

Floatingpoint

float f; // 32 bit floating point double d; // 64 bit floating point real r; // largest hardware implemented floating point ifloat if; //imaginary float idouble id; // imaginary double ireal ir; // imaginary real cfloat cf; // complex number of two float values cdouble cd; // complex double creal cr; // complex real

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

Arrays

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

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

Arrays

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]

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

Arrays mucho más manejables y foreach

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 "~".

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

Arrays mucho más manejables y foreach

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

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

Arrays mucho más manejables y foreachLos 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.

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

String

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

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

String

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

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

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

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

if

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

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

While

while ( /* expresión booleana */ ) sentencia;

ó:

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

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

Switch 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; }

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

Do-While

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

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

For

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

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

Gestión automática de memoria (recolección de basura)En C++ cuando creamos objetos que queremos que transciendan el ámbito de la función, método o bloque de código que los ha creado los creamos con utilizando el operador "new". Este operador se encargará de asignar automáticamente la memoria que sea necesaria para el objeto y llamará a su constructor, devolviéndonos una referencia al objeto ya inicializado que podremos almacenar en una variable del tipo del objeto. Cuando ya no vamos a necesitar el objeto procedemos a borrarlo con el operador "delete" lo que liberará la memoria asignada por el objeto. ¿Parece sencillo verdad? Bien, debería serlo, pero en la práctica es raro el programa en C++ que no tiene o ha tenido una fuga de memoria porque el flujo de ejecución de una parte del mismo termina antes de llegar al delete (y por lo tanto la memoria queda asignada para siempre sin posibilidad de recuperarla) o que ha fallado porque erróneamente se ha hecho un delete del mismo objeto dos veces o se ha intentado acceder (también erróneamente) a un miembro de un objeto previamente borrado.

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

Recolección de basuraObviamente estos errores son evitables pero errar es humano y cuantas más tareas delegue en el programador el lenguaje de programación más posibilidad hay de que haya errores (si no fuera así, todos seguiríamos haciendo ensamblador.) La gestión automática de memoria quiere decir que el programador seguirá creando los nuevos objetos con "new" pero ya no tendrá que preocuparse de borrarlos con "delete" porque existirá un "recolector de basura" que se encargará de eliminar automáticamente los objetos para los que ya no exista ninguna referencia. Es decir, si tenemos la siguiente función: void pierdeaceite() { Obj *o = new Obj(); } En C++ esto produciría una fuga de memoria cada vez que la llamáramos porque al terminar la función ya no habría ninguna referencia a "o" (y por lo tanto no podríamos usarlo) y sin embargo al no haber hecho delete seguiría existiendo en la memoria. El código equivalente en D: void nopierdeaceite() { Obj o = new Obj(); }

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

Recolección de basuraNo produciría ninguna perdida de memoria porque el recolector de basura detectaría que como "o" fue declarado dentro de "nopierdeaceite" y su alcance termina al terminar la función, la memoria puede ser liberada. Esta característica (con la que cuentan también C# y Java) puede desactivarse si por cuestiones de rendimiento o de cualquier otro tipo no queremos que se ejecute el recolector de basura llamando a gc.disable() y luego reactivarse llamando a gc.enable(). Lo más espectacular es que mientras el recolector de basura sigue desactivado las referencias a los objetos que hagamos con "new" se seguirán contabilizando por lo que una vez que re-activemos la recolección de basura esos objetos serán igualmente gestionados (no necesitaremos llamar a delete sobre los mismos.) Esto no es así en C# ni en Java,por ejemplo. Finalmente también podemos borrar, como en C++, nosotros mismos los objetos llamando a "delete" sin que ello cause ningún tipo de conflicto con el recolector de basura.

Page 98: Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria
Page 99: Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria
Page 100: Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria
Page 101: Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria
Page 102: Lenguaje. Historia del lenguaje. Características Procedimientos, funciones y pasajes de parámetros Sistema de tipos Estructuras de control Manejo de memoria

Implementaciones en DImplementaciones en D

-IDE Poseidón

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

Muchas Muchas Gracias!Gracias!

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