Basics ধারণায় একটি ফাংশন ডিফাইন করার দুটি উপায় দেখানো হয়েছে।
সবচেয়ে সাধারণভাবে, বহু-লাইনের রূপটি:
function muladd(x, y, z)
x * y + z
end
সংক্ষিপ্ত সংজ্ঞার জন্য "অ্যাসাইনমেন্ট", বা "একলাইনের" রূপ:
muladd(x, y, z) = x * y + z
তৃতীয়, আরও সংক্ষিপ্ত একটি রূপে ছোট, একবার-ব্যবহৃত একটি ফাংশন নাম ছাড়াই তৈরি করা যায়:
julia> map(x -> 2x, 1:3)
4-element Vector{Int64}:
2
4
6
julia> map((x, y) -> x * y, 1:3, 4:6)
3-element Vector{Int64}:
4
10
18
এক্ষেত্রে x -> 2x হলো একটি "অ্যানোনিমাস ফাংশন"। অন্য কিছু ভাষায় যাকে "ল্যাম্বডা ফাংশন" বলা হয়, এটি তারই সমতুল্য।
মনে রাখবেন, একাধিক আর্গুমেন্ট দিলে বন্ধনী দিতে হয়, যেমন (x, y) -> x * y.
অ্যানোনিমাস ফাংশন জুলিয়া কোডে কমন, বিশেষত map() আর filter()-এর মতো হায়ার-অর্ডার ফাংশন-এর সাথে মিলিয়ে ব্যবহার করলে।
এখন পর্যন্ত পাঠ্যক্রমে আমরা কেবল এমন ফাংশন দেখেছি যেগুলোর আর্গুমেন্টের সংখ্যা নির্দিষ্ট, আর ফাংশন কল করার সময় সেগুলো সবই সঠিক ক্রমে দিতে হয়। এটা সীমাবদ্ধ ও অসুবিধাজনক হতো, তাই আরও কয়েকটি বিকল্প আছে।
অনেক ভাষার মতো জুলিয়াতেও ফাংশনের সংজ্ঞায় আলাদা আলাদা আর্গুমেন্টের জন্য ডিফল্ট মান দেওয়া যায়।
তখন ফাংশন কল করার সময় হয় ওই আর্গুমেন্টের জন্য একটি মান দেওয়া যায়, নাহয় সেটি বাদ দিয়ে ডিফল্ট মানের উপর নির্ভর করা যায়।
julia> f(x, y=10) = x * y
f (generic function with 2 methods)
julia> f(2, 3)
6
julia> f(2)
20
ডিফল্ট ছাড়া সব আর্গুমেন্ট ডিফল্ট সহ যেকোনো আর্গুমেন্টের আগে থাকতে হবে, অর্থাৎ f(x=2, y) অবৈধ হবে।
এখন পর্যন্ত সব উদাহরণে positional arguments ব্যবহার করা হয়েছে, যেখানে ফাংশন কল করার সময় দেওয়া মানগুলোকে ফাংশনের সংজ্ঞায় থাকা সংশ্লিষ্ট আর্গুমেন্টের ক্রমের সাথে মিলতে হয়।
অনেক ভাষার মতো জুলিয়াতেও keyword arguments ব্যবহার করা যায়।
ফাংশন কল করার সময় আর্গুমেন্টের নাম উল্লেখ করতে হয়, তবে একাধিক কিওয়ার্ড আর্গুমেন্ট তখন যেকোনো ক্রমে দেওয়া যায়।
জুলিয়ার একটি বিশেষ বৈশিষ্ট্য হলো, ফাংশনের সংজ্ঞায় কিওয়ার্ড আর্গুমেন্ট থাকলে সেগুলোর আগে একটি সেমিকোলন ; দিতে হয়, যাতে সেগুলো পজিশনাল আর্গুমেন্ট থেকে আলাদা বোঝা যায়।
ফাংশন কল করার সময় শেষ পজিশনাল আর্গুমেন্ট ও প্রথম কিওয়ার্ড আর্গুমেন্টের মাঝে ; বা , দুটোর যেকোনোটি ব্যবহার করা যায়।
julia> b(x; y) = x + y
b (generic function with 1 method)
julia> b(2, y=3)
5
# keyword is required when calling
julia> b(2, 3)
ERROR: MethodError: no method matching b(::Int64, ::Int64)
The function `b` exists, but no method is defined for this combination of argument types.
পজিশনাল আর্গুমেন্টের মতোই ইচ্ছে হলে ডিফল্ট মানও দেওয়া যায়।
প্যারামিটারের সাথে একই নামের একটি ভ্যারিয়েবল আগেই হিসাব করে রাখা হলে, ফাংশন কলের ভেতরে myarg=myarg-এর মতো সিনট্যাক্স লেখার প্রয়োজন হওয়াটা কমন।
এমন পরিস্থিতিতে একটি সংক্ষিপ্ত সিনট্যাক্স ব্যবহার করা যায়:
julia> width = 4.0
4.0
julia> height = √ width
2.0
julia> area(; width, height) = width * height
area (generic function with 1 method)
# repetition
julia> area(; width=width, height=height)
8.0
# shorthand form
julia> area(; width, height)
8.0
জুলিয়া সিনট্যাক্সের একটি উপকারী দিকের নাম এগুলোই, যদি জানতে চান।
দুটোই ... অপারেটরের কথা বোঝায়।
ফাংশন কল করার সময় স্প্ল্যাটিং ব্যবহার করা হয়, যাতে একটি কালেকশন ভেঙে ফাংশনের প্রয়োজনীয় আলাদা আলাদা মান তৈরি হয়।
ব্যাখ্যা করার চেয়ে দেখিয়ে বোঝানো সহজ:
julia> fxyz(x, y, z) = x * y * z
fxyz (generic function with 1 method)
julia> xyz = [2, 3, 4]
3-element Vector{Int64}:
2
3
4
# Using the vector directly in a function call is invalid
julia> fxyz(xyz)
ERROR: MethodError: no method matching fxyz(::Vector{Int64})
The function `fxyz` exists, but no method is defined for this combination of argument types.
# splatting converts the vector to 3 numbers, used as positional arguments
julia> fxyz(xyz...)
24
কিছু "ফাংশন কল" সিনট্যাকটিক সুগারে ঢাকা থাকে, তাই কম স্পষ্ট উপায়েও স্প্ল্যাটিং ব্যবহার করা যায়।
উদাহরণস্বরূপ, একাধিক অ্যাসাইনমেন্ট ভেতরে ভেতরে একটি টাপল কনস্ট্রাক্টর ফাংশন ব্যবহার করে:
julia> first, rest... = [1, 2, 3, 4]
4-element Vector{Int64}:
1
2
3
4
julia> first
1
julia> rest
3-element Vector{Int64}:
2
3
4
কিওয়ার্ড আর্গুমেন্টও স্প্ল্যাটিং করে দেওয়া যায়, সাধারণত একটি named tuple ব্যবহার করে।
Dict-ও কাজ করবে, তবে কী (key)গুলো অবশ্যই সিম্বল হতে হবে (এখানে স্ট্রিং কাজ করবে না)।
# function with 3 keyword arguments
julia> fabc(; a, b, c) = a + b + c
fabc (generic function with 1 method)
# named tuple
julia> abc_nt = (a=2, b=3, c=4)
(a = 2, b = 3, c = 4)
# there are no positional arguments, so need to use ; before kw argument
julia> fabc(;abc_nt...)
9
# Dict
julia> abc_dict = Dict(:a=>2, :b=>3, :c=>4)
Dict{Symbol, Int64} with 3 entries:
:a => 2
:b => 3
:c => 4
julia> fabc(;abc_dict...)
9
ফাংশন সংজ্ঞায় স্লার্পিং ব্যবহার করা হয়, যাতে ইচ্ছেমতো সংখ্যক আলাদা মান একটি কালেকশনে ভরে ফেলা যায়।
julia> f_more(i, j, more...) = i + j + sum(more)
f_more (generic function with 1 method)
julia> f_more(1, 3, 5, 7, 9, 11)
36
স্লার্প করা আর্গুমেন্টের নাম (এক্ষেত্রে more) কোনো তাৎপর্য বহন করে না।
এই ভ্যারিয়েবলের টাইপ কম্পাইলার ঠিক করে, তবে পজিশনাল আর্গুমেন্টের ক্ষেত্রে তা সম্ভবত tuple বা অনুরূপ কিছু হয়।
কিওয়ার্ড আর্গুমেন্টও স্লার্প করা যায়, যার ফলে একটি Dict (বা অনুরূপ কিছু) পাওয়া যায়।
julia> f_kwslurp(x, y; switches...) = :mult in keys(switches) ? x * y : x + y
f_kwslurp (generic function with 1 method)
julia> f_kwslurp(5, 6; mult=true)
30
julia> f_kwslurp(5, 6)
11
কলে যেকোনো কিওয়ার্ড আর্গুমেন্ট ব্যবহার করা যায়। কোন কিওয়ার্ডে সাড়া দেবে আর কোনটি উপেক্ষা করবে, সেটি ঠিক করার দায়িত্ব ফাংশনের সংজ্ঞার।