Tu

Tuplas en Julia

1 ejercicio

Acerca de Tuplas

Una Tuple es bastante similar a un Vector (un array unidimensional) en muchos aspectos. Sin embargo, hay algunas diferencias importantes.

  • Las tuplas se escriben entre paréntesis ( ) en lugar de corchetes [ ], aunque los paréntesis se pueden omitir cuando el significado no es ambiguo.
  • Las tuplas no tienen por qué ser homogéneas: el tipo de cada elemento se almacena de forma independiente.
  • Las tuplas son inmutables.

La inmutabilidad permite más optimizaciones del compilador y hace que las tuplas tengan mejor rendimiento que los vectores, así que conviene preferirlas cuando la mutabilidad no sea necesaria.

julia> t = (3, 5.2, "xyz")
(3, 5.2, "xyz")

# Non-homogeneous:
julia> dump(t)
Tuple{Int64, Float64, String}
  1: Int64 3
  2: Float64 5.2
  3: String "xyz"

julia> t[2]
5.2

# Immutable:
julia> t[2] = 7.3
ERROR: MethodError: no method matching setindex!(::Tuple{Int64, Float64, String}

También existe un constructor Tuple(), que convierte cualquier colección iterable en una tupla. De forma muy útil, esto trata un string como una colección iterable de caracteres.

julia> Tuple("Julia")
('J', 'u', 'l', 'i', 'a')

En cualquier tupla, es posible acceder a los elementos por índice o recorrerlos con un bucle.

Toda tupla puramente numérica también se puede usar en funciones matemáticas como sum(), exactamente igual que los arrays.

Desempaquetado

Se puede desempaquetar una tupla en elementos individuales mediante la asignación múltiple. Para los elementos que no necesites, usa el guion bajo _ como variable ficticia.

julia> tup = (1, "Julia", true)
(1, "Julia", true)

julia> num, name, _ = tup
(1, "Julia", true)

julia> uppercase(name), 2num
("JULIA", 2)

Para copiar todos los elementos de una tupla en otra tupla (o, más en general, en una colección), existe un operador splat ... que la desempaqueta. Esto se tratará con más detalle en el concepto Funciones.

julia> new_tup = (tup..., π, '😊')
(1, "Julia", true, π, '😊')

Tuplas con nombre

Una Tuple solo contiene valores. Una NamedTuple asocia cada valor con un nombre.

Después se puede acceder a los campos individuales con la notación de punto:

julia> nt = (a = 1, b = 7.3)
(a = 1, b = 7.3)

julia> dump(nt)
@NamedTuple{a::Int64, b::Float64}
  a: Int64 1
  b: Float64 7.3

julia> nt.b
7.3

El nombre se almacena internamente como un Symbol (un tipo inmutable, y el nombre va precedido de dos puntos :), así que también hay disponible una sintaxis alternativa:

julia> nt[:b]
7.3

A veces resulta útil dividir la creación de una tupla con nombre en dos pasos:

  1. Definir los campos como un tipo de datos personalizado.
  2. Usarlo como constructor para convertir una tupla en una tupla con nombre.
# Step 1
julia> Student = NamedTuple{(:name, :grade), Tuple{String, Int}}
@NamedTuple{name::String, grade::Int64}

julia> typeof(Student)
DataType

# Step 2
julia> s = Student( ("Helen", 3) )
(name = "Helen", grade = 3)

julia> dump(s)
@NamedTuple{name::String, grade::Int64}
  name: String "Helen"
  grade: Int64 3

Hay sorprendentemente muchas otras formas de crear una tupla con nombre, así que consulta la documentación si te interesa.

Es fácil obtener por separado los nombres (también llamados «claves») o los valores:

julia> keys(s)
(:name, :grade)

julia> values(s)
("Helen", 3)

Ten en cuenta que la iteración sobre una tupla con nombre solo produce los valores, y los nombres se ignoran.

Si los nombres también resultan útiles en una iteración, se necesitan más pasos. La NamedTuple se puede convertir en un Vector de Pairs (los Pair son el tema de otro concepto).

julia> pairs(s)
pairs(::NamedTuple) with 2 entries:
  :name  => "Helen"
  :grade => 3

julia> collect(pairs(s))
2-element Vector{Pair{Symbol, Any}}:
  :name => "Helen"
  :grade => 3

Así pues, la tupla con nombre es bastante similar a un diccionario. Sin embargo, se diferencia de un [Dict][dict] de Julia en algunos aspectos importantes:

  • Un Dict es mutable; una NamedTuple, como cualquier tupla, es inmutable.
  • Un Dict es flexible en el tipo de claves que acepta; una NamedTuple solo puede usar símbolos como claves.

Las tuplas (con nombre o no) son una forma muy común de transferir datos estructurados hacia y desde funciones. La inmutabilidad es buena en este caso, ya que aporta seguridad a los datos y permite optimizaciones del compilador más agresivas.

Editar en GitHub El enlace se abre en una nueva ventana o pestaña

Aprende Tuplas