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.
nothingSi 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).
missingPara 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"
"-"
NaNAbreviatura 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
Es algo que probablemente usarás con menos frecuencia. Entre las excepciones están:
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.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.