空無

空無 在 Julia

1 個練習

關於 空無

許多語言都有像是 null 或 none 這樣的方式,用來表示不存在的值。由於 Julia 的設計目標是處理大量(而且往往很雜亂)的資料,因此它提供了多種表示 空無 的形式。

整體目標是在遇到缺失或可疑的值時把它標記出來,然後繼續執行,而不引發例外。

nothing

如果值真的不存在,就用 nothing 來表示。這應該最接近 C 的 NULL 或 Python 的 None 的做法。

julia> n = nothing

julia> isnothing(n)
true

julia> typeof(n)
Nothing

所以 nothing 是 Nothing 型別的一個單例值,我們可以對它做測試。

nothing 常見的用途之一,是當作只為了副作用而使用的函式(列印、網路設定,或任何類似的事情)的回傳(非)值。

missing

對於值在理論上存在、但我們不知道它是什麼的情況,會使用 missing。例如在計算道路上的車輛數量時,人工觀察員可能需要休息,或是自動感測器會故障,但車流仍持續不斷。

因此 missing 是一個佔位符,用來提醒人們必須決定如何處理資料中的這段缺口。

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

很少有其他語言內建這項功能,但很接近的類似物是 R 的 NA 或 SQL 的 NULL。

上面範例中的向量型別被設為 Union{Missing, Int64},這和其他語言裡的 Option 或 Maybe 之類的型別有些相似。

如果運算式中含有 missing 值,通常預設就會回傳 missing。如果你想忽略這些值,可以使用 skipmissing() 函式,把這個意圖明確表達出來:

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

由於 skipmissing 建立的是疊代器,如果你需要向量,請用 collect() 把它包起來。

有時候,把 missing 值替換成某個預設值會很有用。@coalesce() 巨集很適合這個用途,因為它會回傳第一個不是 missing 的值(如果沒有其他值,就回傳 missing)。

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

NaN 是「Not a Number」的縮寫,用來標示在預期會出現數字的情況下所發生的計算問題。

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

任何包含 NaN 的資料運算,結果都會是 NaN。

目前沒有專門用來移除 NaN 值的函式,但標準的 filter() 函式就能輕鬆做到。只有符合給定條件(結果為 true)的值,才會被複製到結果陣列中:

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

未定義的資料

這是你可能比較少用到的情況。例外情形包括:

  • 可以建立帶有未初始化欄位的複合型別(例如 struct)。 Julia 通常會嘗試使用預設值,但只有在資訊足以推斷欄位型別時才做得到。
  • 在某些情況下,把向量初始化為 undef 可能是既靈活又高效能的作法。 舉例來說,社群對 環形緩衝區 練習的解答就用了這個技巧(這是進階技巧,不過這道練習的難度被評為困難)。

嘗試存取某個值時得到 undef 結果,屬於錯誤狀態,通常會以 UndefRefError 標示。

透過 GitHub 編輯 連結會在新視窗或分頁中開啟

學習 空無