بسیاری از زبانها روشی مانند 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
زبانهای کمی این قابلیت را بهصورت داخلی دارند، اما معادلهای نزدیک آن NA در R یا NULL در SQL است.
نوع بردار در مثال بالا 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"
"-"
NaNNaN که مخفف «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 علامتگذاری میشود.