অনেক ভাষায় 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"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
এটি এমন একটি বিষয় যা আপনি সম্ভবত কম ব্যবহার করবেন। এর ব্যতিক্রমগুলোর মধ্যে আছে:
struct) তৈরি করার উপায় আছে, যেগুলোর ফিল্ড আনইনিশিয়ালাইজড থাকে।
Julia সাধারণত ডিফল্ট মান ব্যবহার করার চেষ্টা করে, কিন্তু ফিল্ডের টাইপ অনুমান করার মতো যথেষ্ট তথ্য থাকলেই তা করতে পারে।undef হিসেবে ইনিশিয়ালাইজ করা একটি নমনীয় ও পারফরম্যান্ট পদ্ধতি হতে পারে।
যেমন, সার্কুলার বাফার অনুশীলনীর কমিউনিটি সলিউশনে এটি ব্যবহার করা হয়েছে (এটি একটি অ্যাডভান্সড কৌশল, তবে অনুশীলনীটিকে কঠিন হিসেবে ধরা হয়েছে)।কোনো মান অ্যাক্সেস করার চেষ্টায় undef ফলাফল পাওয়া একটি এরর অবস্থা, যা সাধারণত UndefRefError দিয়ে চিহ্নিত করা হয়।