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 con paréntesis ( ) en lugar de corchetes [ ], aunque los paréntesis se pueden omitir cuando el significado no es ambiguo.
  • Las tuplas no tienen que ser homogéneas: el tipo de cada elemento se guarda 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 a 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.

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

Desempaquetado

Una tupla se puede desempaquetar en elementos individuales usando 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 a otra tupla (o, más en general, a una colección), existe un operador splat ... que la desempaqueta. Esto se tratará con más detalle en el concepto de Funciones.

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

Tuplas con nombre

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

Luego se puede acceder a cada campo individual 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 guarda internamente como un Symbol (un tipo inmutable, y el nombre lleva el prefijo de dos puntos :), así que hay una sintaxis alternativa disponible:

julia> nt[:b]
7.3

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

  1. Define los campos como un tipo de datos personalizado.
  2. Úsalo 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 te resultan útiles en una iteración, hacen falta 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í, la tupla con nombre se parece bastante 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 sin él) son una forma muy común de transferir datos estructurados desde y hacia las funciones. La inmutabilidad es buena en este caso de uso, ya que brinda seguridad de los datos y permite optimizaciones del compilador más agresivas.

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

Aprende Tuplas