Tema 8: Tipos de datos Sesión 24: Tipos de datos (1) miércoles 4 de mayo de 2011 Referencias • Programming Languages Pragmatics: Capítulo 7, apartados 7.1 (Type Systems) y 7.2 (Type Checking) • Programming in Scala: Capítulo 5 (Basic Types and Operations) y capítulo 11 (Scala's Hierarchy) miércoles 4 de mayo de 2011 Indice • Conceptos generales sobre tipos de datos • Clasificación de tipos • Subtipos • Polimorfismo • Chequeo de tipos • Tipos paramétricos en Scala miércoles 4 de mayo de 2011 Tipos en los lenguajes de programación • Los bytes que se almacenan en la memoria de un computador no tienen tipos de datos: son sólo ceros y unos que se interpretan en función de las instrucciones ejecutadas. • El lenguaje ensamblador tampoco tiene el concepto de tipo, son los lenguajes de alto nivel los que lo introducen miércoles 4 de mayo de 2011 Tipos en los lenguajes de programación • Propósitos principales de los tipos: • Proporcionar contexto implícito en muchas ocasiones, de forma que el programador no tenga que hacerlo explícito. Aumenta la legibilidad y la expresividad de los programas (se pueden decir más cosas con menos líneas de código). • Permiten comprobar errores en programas sintácticamente correctos, limitando la cantidad de fallos que se pueden cometer al desarrollar miércoles 4 de mayo de 2011 Tipos en los lenguajes de programación: contexto implícito • Por ejemplo, en C, la expresión a + b se compila distinto dependiendo del tipo a y b. • En Scala la información de los tipos de datos se utiliza para inferir el tipo de las variables y realizar la compilación a byte codes de Java def factorial(x: BigInt): BigInt = if (x == 0) 1 else x * factorial(x-1) • La función anterior es muy fácil de leer. El hecho de utilizar una x de tipo BigInt permite calcular el factorial de números grandes. En la función se utilizan operadores como * y - sin tener que realizar conversiones de tipos. Y se utilizan las constantes 0 y 1 que, en principio, son de tipo Int. Parece que estamos utilizando tipos normales y no clases. miércoles 4 de mayo de 2011 Tipos en los lenguajes de programación: contexto implícito • Scala transforma el programa anterior en un programa equivalente, utilizando la declaración de la función para saber que x es un objeto de la clase BigInt y la clase de Java java.math.BigInteger: import java.math.BigInteger def factorial(x: BigInteger): BigInteger = if (x == BigInteger.ZERO) BigInteger.ONE else x.multiply(factorial(x.subtract(BigInteger.ONE))) • El primer programa es mucho más expresivo que el segundo. miércoles 4 de mayo de 2011 Tipos en los lenguajes de programación: comprobación de errores • Permiten comprobar errores en programas sintácticamente correctos, limitando la cantidad de fallos que se pueden cometer al desarrollar def sumaStrings(a: String, b: String) = { a+b } var x: Int = 1 var y: Int = 2 sumaStrings(x,y) !!Error!! miércoles 4 de mayo de 2011 Tipos de variables y de objetos • Dos interpretaciones para los tipos de datos: • Tipos declarados para los elementos del lenguaje (variables, parámetros, funciones, etc.) • Tipos de los objetos que se crean en tiempo de ejecución y que se almacenan en las variables, se pasan como parámetros o se devuelven en una función. • Ambos elementos pueden ser distintos, como en el siguiente ejemplo de Scala: var x: AnyVal = 1.0 • El tipo de la variable es AnyVal y el tipo del valor guardado en ella es Double miércoles 4 de mayo de 2011 Tipos de variables y de objetos • Puede no existir tipo para las variables. En Scheme y otros lenguajes débilmente tipeados las variables, parámetros y funciones no se declaran de un tipo; su tipo puede cambiar en tiempo de ejecución: (define a "hola") (set! a (cons 1 2)) (define (suma a b) (+ a b)) (suma 1.0 2.0) (suma (/ 2 3) (/ 1 3)) (define a 1.0) (+ a “hola”) +: expects type <number> as 2nd argument, given: “hola” • Pero los objetos guardados en las variables sí que tienen un tipo definido. El intérprete comprueba en tiempo de ejecución que los tipos de los objetos y las operaciones son compatibles miércoles 4 de mayo de 2011 Definición de tipo • Un tipo es un metadato sobre una estructura del lenguaje (variable u objeto) que define el tipo de dato que vamos a poder guardar en ella. Esta definición especifica de forma implícita el tipo de operaciones que vamos a poder realizar sobre los datos. miércoles 4 de mayo de 2011 Tipos en Scala • Scala es un lenguaje estáticamente tipeado: todas las variables, parámetros, funciones, etc. tienen un tipo definido • La forma de declarar el tipo de una estructura es utilizando dos puntos (:) var x: String = "Hola" def makePlural(c: String): String = { c+"s" } miércoles 4 de mayo de 2011 Tipos en Scala • Scala realiza una inferencia de tipos a partir de las expresiones y podemos no declarar los tipos de las estructuras (en los parámetros de las funciones es obligatorio): var x = "Hola" def makePlural(c: String) = { c+"s" } • La inferencia de tipos de Scala es una idea que toma de los lenguajes de programación funcional ML y Haskell. miércoles 4 de mayo de 2011 Sistemas de tipos • Un sistema de tipos consiste en: • Un mecanismo para definir tipos y asociarlos con ciertas construcciones del lenguaje • Un conjunto de reglas que definen la equivalencia de tipos, compatibilidad de tipos y la inferencia de tipos. miércoles 4 de mayo de 2011 Chequeo de tipos • El chequeo de tipos es el proceso por el que se asegura que el programa obedece las reglas de compatibilidad de tipos • Un error se denomina una colisión de tipos (type clash en inglés) • El chequeo de tipos se puede hacer en tiempo de compilación (lenguaje estáticamente tipeado) y/o en tiempo de ejecución • Por ejemplo, lenguajes como Ada, Pascal, Scala o Java realizan una gran parte del chequeo de tipos en tiempo de compilación • Lenguajes de script como Python, Ruby o Scheme realizan el chequeo de tipos en tiempo de ejecución • Otros lenguajes como ensamblador o C no chequean los tipos en tiempo de ejecución miércoles 4 de mayo de 2011 Clasificación de tipos • Booleano • Carácter • Tipos numéricos • Tipos enumerados • Tipos de subrango • Tipos compuestos miércoles 4 de mayo de 2011 Clasificación de tipos • Tipos compuestos: • Registros • Registros variantes (uniones) • Arrays • Conjuntos • Listas • Ficheros miércoles 4 de mayo de 2011 Booleanos • Los tipos booleanos (true y false) existen en la mayoría de lenguajes de programación • En C no; 1 representa true y 0 false • En Scala: var finalLista: Boolean = false miércoles 4 de mayo de 2011 Carácter • En los lenguajes más antiguos (C, Pascal,…) el tipo carácter tiene un byte de tamaño y guardan el código ASCII del carácter • Los lenguajes más modernos (Java, C#, Scala, …) tienen dos bytes y guardan el código Unicode del carácter • En Scala: var var var var a: Char = 'A' c = '\101' ; número octal c = '\u0041' ; número hexadecimal backslash = '\\' miércoles 4 de mayo de 2011