La

La nada en Julia

1 ejercicio

Acerca de La nada

Muchos lenguajes tienen alguna forma, como null o none, de indicar un valor que no existe. Como Julia está diseñada para manejar grandes volúmenes de datos (a menudo desordenados), tiene varias formas de ausencia de valor.

El objetivo general es señalar los valores faltantes o sospechosos a medida que se encuentran, y luego continuar sin lanzar una excepción.

nothing

Si un valor realmente no existe, se representa con nothing. Esto es probablemente lo más parecido a lo que harían C (NULL) o Python (None).

julia> n = nothing

julia> isnothing(n)
true

julia> typeof(n)
Nothing

Así que nothing es un valor singleton de tipo Nothing, y podemos comprobarlo.

Un uso común de nothing es como valor de retorno (o de no retorno) de funciones que se usan solo por sus efectos secundarios (imprimir, configurar la red o lo que sea).

missing

Para situaciones en las que un valor existe en teoría, pero no sabemos cuál es, se usa missing. Por ejemplo, al contar los vehículos que viajan por una carretera, puede que los observadores humanos necesiten un descanso o que los sensores automáticos fallen, pero el tráfico sigue fluyendo.

Así, missing es un marcador de posición que les advierte a las personas que deben decidir cómo manejar ese hueco en los datos.

julia> mv = [1, 2, missing]
3-element Vector{Union{Missing, Int64}}:
 1
 2
  missing

julia> typeof(mv)
Vector{Union{Missing, Int64}} (alias for Array{Union{Missing, Int64}, 1})

julia> ismissing.(mv)  # broadcast function, displays as 1 for true, 0 for false
3-element BitVector:
 0
 0
 1

Pocos lenguajes más incorporan esta característica, pero hay análogos cercanos: NA en R o NULL en SQL.

El tipo del vector del ejemplo anterior es Union{Missing, Int64}, que tiene cierta similitud con tipos como Option o Maybe de otros lenguajes.

Por lo general, las expresiones devuelven missing si hay valores missing. Si quieres que esos valores se ignoren, usa la función skipmissing() para dejarlo explícito:

julia> mv = [1, 2, missing]
3-element Vector{Union{Missing, Int64}}:
 1
 2
  missing

julia> sum(mv)  # missing in, missing out
missing

julia> skipmissing(mv)
skipmissing(Union{Missing, Int64}[1, 2, missing])

julia> collect(skipmissing(mv))
2-element Vector{Int64}:
 1
 2

julia> sum(skipmissing(mv))  # functions like sum() can work with iterators
3

Como skipmissing crea un iterador, envuélvelo en collect() si necesitas un vector.

A veces es útil reemplazar los valores missing por algún valor predeterminado. La macro @coalesce() es útil para esto, ya que devuelve el primer valor que no sea missing (o true si no hay ningún otro).

julia> str = ["I", "exist", missing]
3-element Vector{Union{Missing, String}}:
 "I"
 "exist"
 missing

julia> [@coalesce(s, "-") for  s in str]
3-element Vector{String}:
 "I"
 "exist"
 "-"

NaN

Abreviatura de «Not a Number», NaN señala un problema de cálculo en situaciones en las que se esperaba un número.

julia> v = [0, 1, -1]
3-element Vector{Int64}:
  0
  1
 -1

julia> v / 0
3-element Vector{Float64}:
 NaN
  Inf
 -Inf
 
julia> sum(v / 0)
NaN

Cualquier tipo de cálculo sobre datos que incluyan un NaN dará como resultado NaN.

Actualmente no existe una función especial para quitar los valores NaN, pero la función estándar filter() puede hacerlo de forma bastante sencilla. Solo se copian al array resultante los valores para los que se cumple una condición dada:

julia> filter(!isnan, [1, 2, NaN])
2-element Vector{Float64}:
 1.0
 2.0

Datos sin definir

Es algo que probablemente usarás con menos frecuencia. Entre las excepciones están:

  • Hay formas de crear tipos compuestos (como struct) con campos sin inicializar. Por lo general, Julia intenta usar valores predeterminados, pero solo puede hacerlo si tiene suficiente información para inferir el tipo del campo.
  • En algunos casos, inicializar un vector como undef puede ser un enfoque flexible y eficiente. Esto se ha usado, por ejemplo, en soluciones de la comunidad al ejercicio Búfer circular (una técnica avanzada, pero está clasificado como un ejercicio difícil).

Obtener un resultado undef al intentar acceder a un valor es un estado de error, que normalmente se señala con un UndefRefError.

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

Aprende La nada