De nombreux langages disposent d'un moyen comme null ou none pour indiquer une valeur inexistante.
Comme Julia est conçu pour traiter de grands volumes de données (souvent désordonnées), il possède plusieurs formes de l'absence de valeur.
L'objectif général est de signaler les valeurs manquantes ou douteuses au fur et à mesure qu'on les rencontre, puis de continuer sans lever d'exception.
nothingSi une valeur n'existe vraiment pas, elle est représentée par nothing. C'est probablement ce qui se rapproche le plus de ce que font le NULL du C ou le None de Python.
julia> n = nothing
julia> isnothing(n)
true
julia> typeof(n)
Nothing
nothing est donc une valeur singleton de type Nothing, et on peut tester sa présence.
L'un des usages courants de nothing est de servir de valeur de retour (ou plutôt de non-valeur) pour les fonctions qu'on n'utilise que pour leurs effets de bord (afficher des choses, configurer le réseau, ou autre).
missingPour les situations où une valeur existe en théorie, mais où on ne sait pas ce qu'elle vaut, on utilise missing. Par exemple, quand on compte les véhicules qui circulent sur une route, les observateurs humains ont parfois besoin de faire une pause, ou bien les capteurs automatiques tombent en panne, alors que le trafic continue de s'écouler.
Ainsi, missing est une valeur de remplacement qui avertit qu'il faut décider comment gérer cette lacune dans les données.
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
Peu d'autres langages intègrent cette fonctionnalité nativement, mais il existe des équivalents proches : NA en R ou NULL en SQL.
Le type du vecteur dans l'exemple ci-dessus est Union{Missing, Int64}, ce qui n'est pas sans rappeler des types comme Option ou Maybe dans d'autres langages.
Les expressions renvoient généralement missing par défaut lorsque des valeurs missing sont présentes.
Si tu veux que ces valeurs soient ignorées, utilise la fonction skipmissing() pour que ce soit explicite :
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
Comme skipmissing crée un itérateur, enveloppe-le dans collect() si tu as besoin d'un vecteur.
Il est parfois utile de remplacer les valeurs missing par une valeur par défaut.
La macro @coalesce() est pratique pour cela, car elle renvoie la première valeur qui n'est pas missing (ou missing s'il n'y a rien d'autre).
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"
"-"
NaNAbréviation de « Not a Number », NaN signale un problème de calcul dans les situations où un nombre était attendu.
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
Tout calcul effectué sur des données contenant un NaN donnera un résultat NaN.
Il n'existe actuellement aucune fonction dédiée pour supprimer les valeurs NaN, mais la fonction standard filter() peut s'en charger très simplement.
Seules les valeurs pour lesquelles une condition donnée vaut true sont copiées dans le tableau final :
julia> filter(!isnan, [1, 2, NaN])
2-element Vector{Float64}:
1.0
2.0
C'est une situation que tu rencontreras sans doute moins souvent. Elle se présente notamment dans les cas suivants :
struct) avec des champs non initialisés.
Julia essaie généralement d'utiliser des valeurs par défaut, mais ne peut le faire que s'il dispose d'assez d'informations pour inférer le type du champ.undef peut être une approche souple et performante.
C'est ce qui a été fait, par exemple, dans des solutions de la communauté à l'exercice Circular Buffer (une technique avancée, mais l'exercice est classé comme difficile).Obtenir un résultat undef en essayant d'accéder à une valeur est un état d'erreur, généralement signalé par une UndefRefError.