Julia প্রোগ্রামারদের উৎসাহ দেয় যতটা সম্ভব কোড এমন ফাংশনের ভেতরে রাখতে, যেগুলো JIT-কম্পাইল করা যায়; আর অনেক ছোট ছোট ফাংশন তৈরি করা ডিজাইন অনুযায়ীই পারফরম্যান্ট।
এর ফলে সাধারণত অনেক ছোট আর সরল ফাংশন তৈরি হয়, যেগুলোকে জটিল কাজ করার জন্য একসাথে জোড়া দিতে হয়।
একটি স্পষ্ট উপায় হলো ফাংশন কল নেস্ট করা। নিচের উদাহরণটি বেশ কৃত্রিম, তবে এটি বিষয়টি বোঝায়।
julia> first.(titlecase.(reverse.(["my", "test", "strings"])))
3-element Vector{Char}:
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
এই উপায়ের অসুবিধা হলো, নেস্টিং যত গভীর হয়, পাঠযোগ্যতা তত দ্রুত কমে যায়।
আমাদের দরকার আরও সরল ও নমনীয় একটি উপায়।
গণিতবিদদের খুব প্রিয় এই কৌশলটির গাণিতিক সিনট্যাক্স Julia হুবহু নকল করে।
∘ অপারেটর (\circ লিখে তারপর ট্যাব চাপলে যা আসে) দিয়ে যেকোনো সংখ্যক ফাংশন একসাথে composed করা যায়।
ফলাফলটিকে একটি একক ফাংশন হিসেবে ব্যবহার করা যায়।
julia> compfunc = first ∘ titlecase ∘ reverse
first ∘ titlecase ∘ reverse
julia> compfunc.(["my", "test", "strings"])
3-element Vector{Char}:
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
# alternative syntax, giving the same result
julia> (first ∘ titlecase ∘ reverse).(["my", "test", "strings"])
কয়েকটি বিষয় লক্ষ করার মতো:
বিকল্প একটি উপায়কে গণিতবিদদের বদলে প্রোগ্রামারদের পদ্ধতি ভাবা যেতে পারে।
Pipelines বহুদিন ধরে Unix শেল স্ক্রিপ্টে ব্যবহৃত হয়ে আসছে, আর সম্প্রতি মূলধারার প্রোগ্রামিং ভাষাগুলোতেও জনপ্রিয় হয়েছে (F#-কে কখনও কখনও এগুলোর ব্যবহার শুরুর কৃতিত্ব দেওয়া হয়)।
মূল ধারণাটি হলো, কিছু ডেটা দিয়ে শুরু করা, তারপর ফলাফল পেতে সেটি ফাংশনের একটি ধারাবাহিকের মধ্য দিয়ে পাইপ করা।
পাইপ অপারেটর হলো |> (F# আর R-এর সাম্প্রতিক সংস্করণে যেমন), তবে Julia-তে ব্রডকাস্ট সংস্করণ .|>-ও আছে।
julia> ["my", "test", "strings"] .|> reverse .|> titlecase .|> first
3-element Vector{Char}:
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
এবার কার্যক্রম কঠোরভাবে বাম থেকে ডানে চলে, প্রতিটি ফাংশনের আউটপুট তীরের দিকে এগিয়ে গিয়ে পরের ফাংশনের ইনপুট হয়ে যায়।
কম্পোজিশন আর পাইপলাইনিং বোঝাতে যে ফাংশনগুলো ব্যবহার করা হয়েছে, সেগুলোর সবগুলোই একটিমাত্র আর্গুমেন্ট নেয়, এটা কোনো কাকতালীয় ব্যাপার নয়।
কিছু বিশুদ্ধ-ফাংশনাল ভাষা প্রথম আর্গুমেন্টটি ফাংশনে পাইপ করে, তবে বাকিগুলোও অন্তর্ভুক্ত করার সুযোগ দেয়।
এর বিপরীতে, Julia পাইপলাইনে শুধু ফাংশনের নাম (বা সমতুল্য কিছু) আশা করে, অতিরিক্ত কোনো আর্গুমেন্ট ছাড়াই।
এর পেছনে গুরুত্বপূর্ণ কারিগরি কারণ আছে (এর সঙ্গে সম্পর্কিত যে currying ভাষার ডিজাইনের আদর্শ অংশ নয়)।
কারিং সম্পর্কে কিছুই না জানা অনেক মানুষকে শুধু মেনে নিতে হবে যে এই সীমাবদ্ধতা কোনো অসতর্ক ভুল নয়, আর ভবিষ্যতের Julia সংস্করণেও এটি বদলানোর সম্ভাবনা নেই।
আমাদের দরকার এমন এক-আর্গুমেন্টের ফাংশন, যা যা দরকার সব করতে পারে। ভাগ্য ভালো, Julia-তে নতুন ফাংশন ডিফাইন করা সহজ।
সবচেয়ে সহজে, আমরা একটি anonymous function ব্যবহার করতে পারি।
উদাহরণস্বরূপ, যদি আমাদের একটি ইনপুট স্ট্রিং থাকে আর আমরা আন্ডারস্কোর দিয়ে ভাগ করতে চাই:
julia> "my_test_strings" |> (s -> split(s, '_'))
3-element Vector{SubString{String}}:
"my"
"test"
"strings"
এরপর সেই ভেক্টরটিকে আগের মতোই অন্য ফাংশনে পাইপ করা যেত।
এই ক্ষেত্রে অ্যানোনিমাস ফাংশনটি বন্ধনীর ভেতরে রাখা ঐচ্ছিক, তবে সাধারণভাবে এটি অস্পষ্টতা কমানোর একটি কাজের উপায়।
একইভাবে, আমরা প্রোগ্রামের আগের অংশে একটি নামযুক্ত ফাংশন তৈরি করে দরকারমতো সেটি আবার ব্যবহার করতে পারি।
এই অনুশীলনীতে আপনি উচ্চ বিদ্যালয়ের প্রেমিক-প্রেমিকাদের সামাজিক মাধ্যমে তাদের ভালোবাসা প্রকাশ করতে সাহায্য করবেন, তাদের নামের আদ্যক্ষর দিয়ে একটি ইউনিকোড হার্ট তৈরি করে:
❤ J. + M. ❤
cleanupname মেথডটি ইমপ্লিমেন্ট করুন।
এটি একটি নাম নেবে এবং নামটি থেকে সব - ক্যারেক্টার মুছে ফেলে সেগুলোর জায়গায় একটি স্পেস বসাবে।
এটি নামের শুরু ও শেষ থেকে যেকোনো হোয়াইটস্পেসও মুছে ফেলবে।
julia> cleanupname("Jane-Ann")
"Jane Ann"
firstletter মেথডটি ইমপ্লিমেন্ট করুন।
এটি একটি নাম নেবে এবং তার প্রথম অক্ষরটি একটি স্ট্রিং হিসেবে রিটার্ন করবে।
আগের ধাপে আপনি যে cleanupname ডিফাইন করেছিলেন সেটি আবার ব্যবহার করতে ভুলবেন না এবং তা অন্য ফাংশনের সঙ্গে কম্পোজ করুন।
julia> firstletter("Jane")
"J"
initial মেথডটি ইমপ্লিমেন্ট করুন।
এটি একটি নাম নেবে এবং তার প্রথম অক্ষরটি বড় হাতের অক্ষরে রিটার্ন করবে, যার পরে একটি ডট থাকবে।
আগের ধাপে আপনি যে firstletter ডিফাইন করেছিলেন সেটি আবার ব্যবহার করতে ভুলবেন না।
initial("Robert")
"R."
couple মেথডটি ইমপ্লিমেন্ট করুন।
এটি দুটি নাম নেবে এবং দুপাশে ইমোজি হার্ট দিয়ে আদ্যক্ষরগুলো রিটার্ন করবে।
আগের ধাপে আপনি যে initial ডিফাইন করেছিলেন সেটি আবার ব্যবহার করতে ভুলবেন না।
couple("Blake Miller", "Riley Lewis")
"❤ B. + R. ❤"
Exercism-এ সাইন আপ করুন, Julia ট্র্যাকের 35টি কনসেপ্ট128টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।