এখন পর্যন্ত সিলেবাসে টাইপ নিয়ে বিশেষ কিছু বলা হয়নি, তবে Julia-তে যে টাইপ আছে, তা স্পষ্টই:
julia> vals = (42, 4.3, π, "hello", 'Q')
(42, 4.3, π, "hello", 'Q')
julia> typeof(vals)
Tuple{Int64, Float64, Irrational{:π}, String, Char}
আমরা কখনও টাইপ নির্দিষ্ট করিনি, তবুও Julia সেগুলো নিজে থেকেই অ্যাসাইন করে দিয়েছে।
types আছে, যা এর ডিজাইনের কেন্দ্রে রয়েছে।Type Inference ব্যবহার করে টাইপটি "অনুমান" করতে পারে।JIT কম্পাইলার (সব) কোড দেখে নেবে, একটি ভ্যারিয়েবল কীভাবে ব্যবহৃত হচ্ছে তা দেখবে, এবং সেই ব্যবহারের সঙ্গে মানানসই একটি উপযুক্ত ডিফল্ট টাইপ ইনফার করবে।
সাধারণ টিউটোরিয়াল অনুশীলনী সমাধান করার জন্য টাইপ ইনফারেন্সের ওপর ভরসা করা ঠিকই আছে, কিন্তু বড় প্রোগ্রামের ক্ষেত্রে আপনার আরও নিখুঁত নিয়ন্ত্রণ দরকার হতে পারে।
বেশিরভাগ আধুনিক প্রসেসরে একটি ইন্টিজারের ডিফল্ট টাইপ Int64 হয়।
Numbers কনসেপ্টে আমরা দেখেছি, একটি মানকে নির্দিষ্ট কোনো ডিফল্ট-বহির্ভূত টাইপে রূপান্তর করা যায়।
julia> x = Int16(42)
42
julia> typeof(x)
Int16
তবে ভ্যারিয়েবলটিকে x এখনও ভিন্ন একটি টাইপে আবার অ্যাসাইন করা যায়:
julia> x = "changed"
"changed"
julia> typeof(x)
String
একে বলে type instability, যা হলো:
বদলে, :: অপারেটর ব্যবহার করে আমরা x-এর টাইপ নির্দিষ্ট করে দিতে পারি:
julia> y::Int16 = 42
42
julia> typeof(y)
Int16
julia> y = "changed"
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int16
The function `convert` exists, but no method is defined for this combination of argument types.
এখন y-এর টাইপ Int16, এবং সবসময় তাই থাকবে।
ফলে কম্পাইলার জানে এর জন্য কত বাইট সংরক্ষণ করতে হবে, আর স্থির একটি টাইপের ওপর ভরসা করে বাকি কোডটি অপ্টিমাইজ করতে পারে।
এই দিক থেকে ভ্যারিয়েবলটি C-এর মতো স্ট্যাটিক-টাইপড ভাষার ভ্যারিয়েবলের সঙ্গে কমবেশি একই রকম।
Int64, Int16, String, Char: এই টাইপগুলো আসে কোথা থেকে।
অনেক অবজেক্ট-ওরিয়েন্টেড (OO) ভাষায় প্রতিটি টাইপ একটি ক্লাস, সাবক্লাসিং তাদের একটি ক্লাস হায়ারার্কিতে সাজায়, আর ক্লাস মেথডগুলো আচরণ নির্ধারণ করে।
Java আর Ruby এই প্যাটার্নের স্পষ্ট উদাহরণ, তবে Python-ও ভেতরে ভেতরে একই রকম।
Julia-তে কোনো ক্লাস নেই।
নথিভুক্ত কারণটি হলো, OO ফিচারগুলো JIT কম্পাইলারের কাজে বাধা দেয় এবং রানটাইম পারফরম্যান্স নষ্ট করে।
তবুও, এই কোডটি দেখুন:
julia> y::Int16 = 42
42
julia> typeof(y)
Int16
julia> supertype(Int16)
Signed
julia> supertypes(Int16)
(Int16, Signed, Integer, Real, Number, Any)
কিছু বিবরণ যোগ করলে:
Int16 একটি টাইপ, এবং আমরা এই টাইপের ভ্যারিয়েবল বানাতে পারি।Int16 হলো Signed টাইপের একটি সাবটাইপ, এবং supertype() ফাংশনটি তা আমাদের দেখায়।Integer, Real এবং Number হয়ে একেবারে ওপরে Any পর্যন্ত ওঠে, আর subtypes() আমাদের জন্য হায়ারার্কির এই শাখাটি তালিকাভুক্ত করবে।সব শাখাই শেষ হয় Any-তে, যেটি অনন্য এই অর্থে যে এটিই নিজের সুপারটাইপ।
julia> supertypes(String)
(String, AbstractString, Any)
julia> supertype(Any)
Any
তাহলে, Julia-তে কোনো class হায়ারার্কি নেই, তবে type হায়ারার্কি আছে।
একসময় আমরা এটি কীভাবে কাজ করে তা খুঁটিয়ে দেখব, তবে আগে আরও অনেক কিছু ঘুরে দেখার বাকি আছে।
সাধারণ উপায়েই আমরা সমতা পরীক্ষা করতে typeof() ব্যবহার করতে পারি।
julia> typeof(11)
Int64
julia> typeof(11) == Int64
true
julia> typeof(11) == Number
false
টাইপের সমতা অবশ্যই হুবহু হতে হবে, কারণ তুলনার এই রূপটি টাইপ হায়ারার্কি সম্পর্কে কিছুই জানে না।
আরও নমনীয়ভাবে, isa আমাদের জানাবে একটি মানের টাইপ তুলনাকারী টাইপের সমান কি না, কিংবা তার সাবটাইপ কি না।
এটি ফাংশন আকারে বা ইনফিক্স আকারে, দুইভাবেই ব্যবহার করা যায়।
julia> 12 isa Int64
true
julia> 12 isa Number
true
julia> isa(12, Number)
true
julia> 12 isa String
false
লক্ষ্য করুন, isa বাম দিকে একটি value আশা করে, type নয়।
এইভাবে দুটি টাইপ তুলনা করতে গেলে অপ্রত্যাশিত ফলাফল আসবে।
সঠিক অপারেটরটি হলো <:, যা আমরা ভবিষ্যতের কনসেপ্টগুলোতে আরও অনেকবার দেখব।
julia> Int64 isa Number ## Don't do this!
false
julia> Int64 <: Number
true
আমরা দেখেছি, টাইপ হায়ারার্কি একটি গাছের কাঠামো তৈরি করে (কম্পিউটার সায়েন্সের অর্থে, যার মূল থাকে একেবারে ওপরে)।
গাছের প্রতিটি উপাদান একটি node, এবং এগুলোকে কয়েকটি শ্রেণিতে ভাগ করা যায়:
abstract বলা হয়।concrete বলা হয়।julia> subtypes(Integer) # an abstract type
3-element Vector{Any}:
Bool
Signed
Unsigned
julia> subtypes(Int64) # a concrete type
Type[]
এটি একটি গুরুত্বপূর্ণ পার্থক্য, কারণ কেবল কংক্রিট টাইপকেই ভ্যারিয়েবল হিসেবে instantiated করা যায়।
julia> a::Int16 = 42
42
julia> typeof(a)
Int16
julia> b::Integer = 42
42
julia> typeof(b)
Int64
লক্ষ্য করুন, একটি অ্যাবস্ট্রাক্ট টাইপ ব্যবহার করতে গেলে (এই ক্ষেত্রে) কোনো এরর বার্তা আসে না, বরং কম্পাইলার উপযুক্ত একটি কংক্রিট টাইপ তৈরি করে: Integer-এর বদলে Int64।
এই অনুশীলনীতে আপনি কিছু গ্রেডিং ডেটা প্রিপ্রসেস করে একটু ডেটা ইঞ্জিনিয়ারিং করবেন। অনেক, অনেক, অনেক (অতি বেশি?) শিক্ষার্থীর একটি স্কুল শিক্ষার্থীদের পাওয়া গ্রেড নিয়ে কিছু ডেটা অ্যানালাইসিস করতে চাইছে এবং সেটি দক্ষতার সাথে করতে চাইছে, তাই লক্ষ্য হলো ডেটা যতটা সম্ভব কমানো এবং গুছিয়ে ফেলা।
গ্রেডিং স্কেল সাধারণত ০ থেকে ১০ পর্যন্ত হয়, তাই প্রতি গ্রেডে মাত্র আট বিট থাকে এমন একটি ডেটা টাইপ ব্যবহার করাই সবচেয়ে কার্যকর।
UInt8 ডেটা টাইপে কনভার্ট করতে হবে।Int8 ডেটা টাইপে কনভার্ট করতে হবে।গ্রেড কনভার্ট করার ফাংশনটি তৈরি হয়ে গেলে, গ্রেডগুলো যে কালেকশনে রাখা আছে সেগুলো সামলানোর জন্য আপনাকে আরেকটি ফাংশন লিখতে হবে, যা গ্রেডগুলো ডিমোট করে অবরোহক্রমে রিটার্ন করবে।
Vector ব্যবহার করেন।Set ব্যবহার করেন, যেগুলো সাজানো থাকে না।দুটি ফাংশনেই, অবৈধ ইনপুট সামলাতে আপনাকে একটি MethodError থ্রো করতে হবে।
এক্সেপশন হ্যান্ডলিং পরের কোনো কনসেপ্টে আলোচনা করা হবে, তাই এই অনুশীলনীর উদ্দেশ্যে আপনি নিচের সিনট্যাক্সটি ব্যবহার করতে পারেন:
throw(MethodError(f, args))
এখানে f হলো ফাংশন, আর args হলো ফাংশনে দেওয়া আর্গুমেন্টগুলোর একটি টাপল।
demote(n) ফাংশনের ক্ষেত্রে f হলো demote আর args হলো (n,):
throw(MethodError(demote, (n,)))
demote(n) মেথডটি ইমপ্লিমেন্ট করুন।
Float64 ইনপুট পেলে, এটি নিকটতম পূর্ণসংখ্যায় রাউন্ড আপ করবে এবং একটি UInt8 ডেটা টাইপ রিটার্ন করবে।Integer ইনপুট পেলে, এটি একই ইন্টিজার একটি Int8 ডেটা টাইপে রিটার্ন করবে।julia> demote(4.2)::UInt8
5
julia> demote(4)::Int8
4
julia> demote("hi")
MethodError: no method matching demote(::String) #output truncated
preprocess(coll) মেথডটি ইমপ্লিমেন্ট করুন।
Vector ইনপুট পেলে, এটি সব সংখ্যা ডিমোট করবে এবং ভেক্টরটি উল্টে দেবে।Set ইনপুট পেলে, এটি সব সংখ্যা ডিমোট করবে এবং অবরোহক্রমে সাজানো একটি ভেক্টর রিটার্ন করবে।julia> preprocess([1, 2, 3])
3-element Vector{Int8}:
3
2
1
julia> preprocess(Set([2.2, 5.8, 3.4]))
3-element Vector{UInt8}:
6
4
3
julia> preprocess(42)
MethodError: no method matching preprocess(::Int64) #output truncated
Exercism-এ সাইন আপ করুন, Julia ট্র্যাকের 35টি কনসেপ্ট128টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।