توفّر لغات كثيرة وسيلة مثل 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.
تُرجع التعبيرات عادةً 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اختصارًا لعبارة "Not a Number"، تشير NaN إلى مشكلة حسابية في الحالات التي كان يُتوقع فيها عدد.
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
في هذا التمرين ستكتب كودًا لإنشاء شارات أسماء يرتديها موظفو المصنع. لكل موظف معرّف واسم واسم قسم. تُنسَّق ملصقات شارات الموظفين على النحو التالي: "[id] - name - DEPARTMENT".
نفّذ الدالة print_name_badge. يجب أن تأخذ معرّفًا واسمًا وقسمًا. ويجب أن تُرجع ملصق الشارة، مع اسم القسم بأحرف كبيرة.
julia> print_name_badge(67, "Katherine Williams", "Strategic Communication")
"[67] - Katherine Williams - STRATEGIC COMMUNICATION"
بسبب خلل في نظام الحاسوب، لا يكون لدى الموظفين الجدد معرّف في بعض الأحيان عند بدء عملهم في المصنع. ولأن الشارات مطلوبة، فسيحصلون على شارة مؤقتة بدون بادئة المعرّف.
وسّع الدالة print_name_badge. عندما يكون المعرّف مفقودًا، يجب أن تُنشئ شارة بدونه.
julia> print_name_badge(missing, "Robert Johnson", "Procurement")
"Robert Johnson - PROCUREMENT"
حتى مالك المصنع عليه أن يرتدي شارة في جميع الأوقات. غير أن المالك ليس له قسم ولن يكون له أبدًا: فهو فوق كل الأقسام. في هذه الحالة، يجب أن يُرجع الملصق "OWNER" بدلًا من اسم القسم.
وسّع الدالة print_name_badge. عندما يكون القسم nothing، افترض أن الشارة تخص مالك الشركة.
julia> print_name_badge(204, "Rachel Miller", nothing)
"[204] - Rachel Miller - OWNER"
لاحظ أنه من الممكن أن يكون المالك أيضًا موظفًا جديدًا.
julia> print_name_badge(missing, "Rachel Miller", nothing)
"Rachel Miller - OWNER"
بوصفها مقياسًا تقريبيًا لمدى جودة إصدار المعرّفات، تريد أن ترى الرواتب المجمّعة للموظفين الذين لا يملكون معرّفًا. القيمة العالية تعني أن هناك الكثيرين في الانتظار، أو أن المشكلة تؤثر على أصحاب المناصب العليا: وكلاهما سيئ.
نفّذ الدالة salaries_no_id التي تأخذ متجهًا من المعرّفات ومتجهًا مقابلًا من الرواتب، وتُرجع مجموع رواتب الأشخاص الذين لا يملكون معرّفًا بعد. المتجهان لهما الطول نفسه.
julia> ids = [204, missing, 210, 352, missing, 263]
julia> salaries = [23, 21, 47, 35, 17, 101] * 1000
julia> salaries_no_id(ids, salaries)
38,000
سجّل في Exercism لتتعلّم وتتقن Julia عبر 35 مفهومًا128 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.