Los tipos en Julia son básicamente los elementos de datos de diferentes tamaños y funcionalidades. Cada valor (no variable) en un programa está destinado a ser de algún tipo. Las variables son simplemente nombres vinculados a algunos valores. La definición del tipo de valor la realiza el programador o el propio compilador. Siempre se considera factible definir el tipo del valor antes de ejecutar el código fuente para lograr una ejecución rápida y hacer que su código sea menos propenso a errores.
Ejemplo: Considere los siguientes tres valores:
10 -> Integer, 10.5 -> Float, 10/3 -> Rational
Cada valor aquí es de un tipo diferente. El valor entero es diferente de un valor flotante y del valor racional y, de manera similar, los otros dos valores son diferentes entre sí. Ahora, si tenemos que sumar estos tres valores o realizar alguna otra operación con estos valores, entonces será una dificultad porque los valores no son del mismo tipo. Para sumar estos valores, necesitamos convertir los otros dos valores para que sean del mismo tipo que el tercero.
El Sistema Tipo se divide básicamente en dos categorías, en función del momento de su definición. Estos son:
- Sistema de tipo estático
- Sistema de tipos dinámicos
Sistema de tipos estáticos: en un sistema de tipos estáticos, cada expresión de programa ejecutable se define con un tipo antes de su ejecución. Esto se hace al final del programador y es factible para una mayor velocidad de ejecución del código.
Sistema de tipos dinámicos: en un sistema de tipos dinámicos, el compilador tiene que decidir el tipo de los valores en el momento de la compilación del código. Esto hará que el código tarde un poco más en ejecutarse.
Julia usa Dynamic Typed System para escribir valores de variables, pero también acepta definiciones de tipos estáticos para proporcionar la ventaja de indicar que ciertos valores son de tipos específicos. De forma predeterminada, Julia asigna los valores sin tipo con cualquier tipo requerido. Por lo tanto, el programador puede escribir cualquier función de Julia sin tener que definir los tipos explícitamente. Pero proporcionar un tipo explícito al valor da como resultado una mejor legibilidad del código y también facilita la búsqueda de errores en el código. Por lo tanto, no es necesario usar el sistema Type en Julia, pero usarlo hará que el código sea más claro, simple, rápido y robusto.
Declaración de Tipos
Los tipos en Julia se declaran con la ayuda del operador :: . Este operador se lee como ‘es una instancia de’ cuando se agrega a un valor o una expresión. Se puede usar en cualquier parte del programa para mostrar que el valor del lado izquierdo es una instancia del tipo definido en el lado derecho del operador :: .
Los tipos se declaran para hacer una prueba de la afirmación para confirmar que el programa funciona bien y para proporcionar al compilador información adicional sobre el tipo de las expresiones y valores que darán como resultado un código más rápido y eficiente.
Ahora, podría pensar qué sucede si el programador desconoce el tipo y asigna un tipo incorrecto al valor o expresión. Esto es manejado por una excepción en Julia. Si el valor del lado izquierdo no es del tipo que se declara en el lado derecho, se genera una excepción y la ejecución del código se detendrá allí. Porque el compilador espera que el valor calculado en el lado izquierdo sea del tipo especificado en el lado derecho. La excepción planteada indicará el tipo esperado desde el lado izquierdo (como se define) y lo que realmente se está produciendo.
Ejemplo:
En el fragmento anterior, se puede ver que cuando la expresión del lado izquierdo se define con un tipo Float, genera un error en la ejecución porque se esperaba que el valor calculado a la izquierda fuera del tipo Float64 como se declaró, pero es del tipo Int64 . Más tarde, cuando el sistema Tipo se cambió a Int, calculó el valor en el lado izquierdo y produjo la salida.
Uso de la definición de tipo con el operador de asignación: cuando se usa con el operador de asignación, el operador :: si se usa para hacer que la variable en el lado izquierdo sea un valor escrito, entonces restringirá esa variable para que siempre contenga el valor del mismo tipo, al igual que las variables tipadas estáticamente en lenguaje C. Cada valor asignado a la variable, si no es del mismo tipo, se convertirá al mismo tipo con el uso de la convert
función.
Ejemplo:
Nota: La declaración de la variable con tipo se limita solo a las variables locales. Por ahora, Julia no permite escribir variables globales.
La declaración de tipo para funciones también está permitida en Julia. Esto dará como resultado que la función siempre convierta y devuelva el valor calculado en la forma del Tipo especificado.
Ejemplo:
function Addition(x, y)::Float64 return x + y end Addition(1, 2)
En el código anterior, la función debería devolver el valor Integer, pero debido a la declaración de tipo de la función, la salida del valor calculado se convierte en Float64 (tipo deseado).
Tipos concretos y tipos abstractos
Julia permite que cada objeto tenga un tipo, pero no es seguro que tenga instancias de todos los tipos. Los tipos que pueden tener instancias se conocen como tipos concretos . Los tipos concretos no pueden tener subtipos. Los subtipos son las subentidades de un tipo. Si un tipo se puede dividir en diferentes tipos, esas partes se denominan subtipos. Por ejemplo, Strings, Rational, bool, etc.
Los tipos abstractos son aquellos cuyos subtipos existen. Por ejemplo, Any, Number, etc. Aunque no podemos crear objetos de tipos Abstract pero con la ayuda de tipos Abstract, un programador puede escribir códigos que pueden funcionar con cualquiera de los subtipos del tipo especificado.
Ejemplo:
function Addition(x::Number) return x + 1 end
El código anterior puede aceptar un número de cualquier subtipo, es decir, aceptará Float64, Int64, etc. y devolverá la salida de la misma forma. Porque aquí, x se escribe con ::Number , entonces x debe ser un subtipo de Number. Generará un error si el valor de x es diferente a un subtipo de Número como String, array, etc.
Los subtipos de un tipo se pueden escribir con el uso del símbolo <:. Este símbolo significa que el lado izquierdo es is a subtype of
el lado derecho. También se puede usar en una expresión para probar si el operando del lado izquierdo es un subtipo del operando derecho. Devolverá verdadero para el mismo y falso si no es un subtipo del tipo especificado.
Ejemplo:
Los tipos abstractos se pueden usar para proporcionar implementaciones predeterminadas para tipos concretos. Si tomamos un ejemplo en el que la implementación por defecto es de cualquier tipo. Luego, el compilador asignará los subtipos respectivos a los valores según la necesidad del cálculo.
function Addition(x, y) return x + y end Addition(1, 2)
Al ejecutar el código anterior, el compilador asignará automáticamente el tipo de los argumentos pasados como el tipo de los valores en la función.
function Addition(x::Int, y::Int) return x + y end Addition(1, 2)
Los tipos de hormigón se pueden dividir en dos tipos:
- tipos primitivos
- Tipos compuestos
tipos primitivos
Los Tipos Primitivos en Julia son los tipos concretos cuyo valor está en forma de bits. Los valores enteros y flotantes son un ejemplo de tipos primitivos. Julia tiene un conjunto predefinido de tipos primitivos estándar, pero también permite crear sus propios tipos.
Sintaxis para declarar un tipo primitivo:
primitive typeend primitive type <: end
Ejemplos de tipos primitivos son Int8, Int16, Int64, Float16, Float32, String, etc.
Los tipos abstractos no se pueden usar para almacenar valores en la memoria, el compilador asignará automáticamente un tipo primitivo al valor. Si verificamos el tamaño del tipo abstracto Integer, generará un error porque Integer no tiene un tamaño fijo, pero podemos verificar el tamaño de sus tipos primitivos, es decir, Int8, Int16, Int64, etc.
Tipos compuestos
Los tipos compuestos en Julia son una colección de campos con nombre que se pueden tratar individualmente como valores únicos de tipos específicos. Los tipos compuestos se pueden declarar con el uso de la palabra clave struct .
Sintaxis:
structField_name1 Field_name2::Type Field_name3::Type end
Aquí, los campos que no se especifican con ningún tipo se establecen con el tipo predeterminado Cualquiera . El objeto de este tipo compuesto se puede crear con el uso de constructores.
Ejemplo:
# Creating composite types struct Geeks x y::Int64 z::Float64 end # creating object with constructor object1 = Geeks("Hello", 10, 10.5)
Como podemos ver en el código anterior, el tipo compuesto se crea con el uso de la palabra clave struct y todos los campos son individualmente de tipos primitivos. Si verificamos el tipo del objeto creado con el uso del constructor, entonces muestra la estructura que se ha creado.
Nota: los tipos compuestos creados con el uso de la palabra clave struct son inmutables, lo que significa que no se pueden modificar después de su creación.
Tipos compuestos mutables
Los tipos compuestos definidos con el uso de struct son de tipos inmutables como se explicó anteriormente. Pero, Julia también permite crear tipos Compuestos de tipos Mutables, lo que significa que el valor de su campo puede modificarse incluso después de su creación. Esto se hace mediante el uso de la palabra clave mutable struct . Si un tipo compuesto se declara con una estructura mutable en lugar de una estructura , el valor de sus instancias se puede modificar en cualquier momento.
mutable structField_name1 Field_name2::Type Field_name3::Type end
Ejemplo:
# Creating composite types # with mutable struct struct Geeks x y::Int64 z::Float64 end # creating object with constructor object1 = Geeks("Hello", 10, 10.5)
Los valores de una estructura mutable se pueden modificar simplemente pasando el nuevo valor al campo.