কালেকশন

লিস্ট, টাপল, কীওয়ার্ড লিস্ট এবং ম্যাপ

Lists

লিস্ট হচ্ছে এমন একটি কালেকশন যা যে কোন মান কে সংগ্রহে রাখে। লিস্টে একই রকম একাধিক ভ্যালু (মান) থাকতে পারে:

iex> [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]

এলিক্সির লিস্ট সমূহ “লিঙ্কড লিস্ট” আকারে সংরক্ষিত। তার মানে হল, লিস্টের দৈর্ঘ্য জানতে O(n) সময় লাগবে। এ কারণে লিস্টের বাম থেকে (সম্মুখে) ডাটা এন্ট্রি দেওয়া দ্রুততর, ডান থেকে (শেষপ্রান্তে) নয়।

iex> list = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
# সম্মুখে কোন মান যোগ করা (দ্রুততর)
iex> ["π" | list]
["π", 3.14, :pie, "Apple"]
# শেষ প্রান্তে কোন মান যোগ করা (ধীরগতির)
iex> list ++ ["Cherry"]
[3.14, :pie, "Apple", "Cherry"]

লিস্ট কনক্যাটিনেশন (একত্রকরণ)

লিস্ট কনক্যাটিনেট (একত্র) করতে ++/2 ব্যবহৃত হয়:

iex> [1, 2] ++ [3, 4, 1]
[1, 2, 3, 4, 1]

++/2 ফরম্যাট নিয়ে কিছু কথা, এলিক্সির (এবং এরল্যাং, যার উপর এলিক্সির বানানো) প্রোগ্রামিং ল্যাঙ্গুয়েজে কোন ফাংশন অথবা অপারেটরের নাম দুই ভাগে বিভক্ত- ১) নাম যা সেই ফাংশনের অথার দিয়ে থাকেন (এই ক্ষেত্রে- ++) এবং ২) তার আরিটি, অর্থাৎ, ফাংশন অথবা অপারেটরটি কয়টি আর্গুমেন্ট নিতে পারে। ১) ও ২) একটি “ফরওয়ার্ড স্ল্যাশের” মাধ্যমে যুক্ত থাকে। আপাতত আমাদের এতটুকু জানলেই চলবে, এ বিষয়ে পরে আরও আলোচনা করা হবে।

লিস্ট সাবট্র্যাকশন (কোন মান বাদ দেওয়া)

লিস্ট থেকে কোন মান বাদ দিতে --/2 অপারেটর ব্যবহার করা হয়ে থাকে; যা বিয়োগ করছেন তা যদি লিস্টে অনুপস্থিত থাকে তাহলেও কোন সমস্যা নেই:

iex> ["foo", :bar, 42] -- [42, "bar"]
["foo", :bar]

একই ভ্যালু লিস্টে একাধিক বার থাকলে একটু সচেতন থাকতে হবে। তবে আপনি যে ভ্যালু বাদ দিতে চাচ্ছেন তা যদি লিস্টে একাধিকবার থাকে তাহলে বামদিক থেকে বাদ দেওয়া শুরু হবে-

iex> [1,2,2,3,2,3] -- [1,2,3,2]
[2, 3]

দ্রষ্টব্য: এটি স্ট্রিক্ট কম্প্যারিশন ব্যবহার করে ভ্যালু ম্যাচ করার জন্য।

হেড/টেইল

লিস্ট ব্যবহার করার সময়ে প্রায়েই হেড (লিস্টের প্রথম ভ্যালু) এবং টেইল (লিস্টের বাকি ভ্যালু) জানার দরকার পরে। এলিক্সির দুইটি ফাংশন দিয়েছে এর জন্যে, যা হল- hdtl। উদাহরণ-

iex> hd [3.14, :pie, "Apple"]
3.14
iex> tl [3.14, :pie, "Apple"]
[:pie, "Apple"]

এছাড়াও আমরা প্যাটার্ন ম্যাচিং এবং কন্স অপারেটর | দিয়েও একটি লিস্টকে দুই ভাগে ভাগ করতে পারি যা সম্পর্কে পরে আলোচনা করা হবে।

iex> [head | tail] = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
iex> head
3.14
iex> tail
[:pie, "Apple"]

টাপল

টাপল লিস্টের মতই একটি কালেকশন কিন্তু টাপলে ডাটা একাধারে সংরক্ষিত থাকে। এর মানে হল, টাপলের দৈর্ঘ্য জানা যায় অনেক দ্রুত কিন্তু টাপলের মান চেঞ্জ করা একটু মুসকিল হয়ে পড়ে। টাপ্লকে মডিফাই করতে হলে পুরা ডাটাকে মেমরিতে রাখা লাগে তাই টাপল মডিফিকেশন না করাই ভাল।

iex> {3.14, :pie, "Apple"}
{3.14, :pie, "Apple"}

টাপল প্রায়েই ব্যবহৃত হয় ফাংশনের রীটার্ন ভ্যালু হিসেবে যখন অতিরিক্ত ডাটা প্রয়োজন, এ সম্পর্কে আরও জানা যাবে যখন আমরা প্যাটার্ন ম্যাচিং করব:

iex> File.read("path/to/existing/file")
{:ok, "... contents ..."}
iex> File.read("path/to/unknown/file")
{:error, :enoent}

কী-ওয়ার্ড লিস্ট

কী-ওয়ার্ড ও ম্যাপ হল এলিক্সিরের অ্যাসোসিয়েটিভ কালেকশন।

এলিক্সিরে কী-ওয়ার্ড হল বিশেষ লিস্ট যার প্রতিটি মান হচ্ছে ২ সদস্য বিশিষ্ট টাপ্ল যার প্রথম ডাটা হল অ্যাটম। এদের পারফর্মেন্স লিস্টের সমকক্ষ।

iex> [foo: "bar", hello: "world"]
[foo: "bar", hello: "world"]
iex> [{:foo, "bar"}, {:hello, "world"}]
[foo: "bar", hello: "world"]

কী-ওয়ার্ড লিস্টের তিনটি বিশেষ গুণাবলী:

এই কারন গুলির কারনে কী-ওয়ার্ড লিস্ট সাধারণত ফাংশনের অতিরিক্ত প্যারামিটার (অপ্সনাল) হিসেবে ব্যবহৃত হয়ে থাকে।

ম্যাপ

এলিক্সিরে ম্যাপ হল আন-ওর্ডারড কী/ভ্যালু স্টোর। কি ওয়ার্ড লিস্টের মত দেখতে মনে হলেও, কি ওয়ার্ড লিস্টের সাথে ম্যাপের মূল পার্থক্য হচ্ছে এখানে কি হিসাবে যেকোন টাইপ ব্যবহার করা যায় এবং ম্যাপ আনঅর্ডারড। খালি ম্যাপকে %{} সিনট্যাক্স দিয়ে বানানো হয়:

iex> map = %{:foo => "bar", "hello" => :world}
%{:foo => "bar", "hello" => :world}
iex> map[:foo]
"bar"
iex> map["hello"]
:world

ভার্সন ১.২ থেকে আপনি ভেরিয়েব্লকে কী হিসেবে ব্যবহার করতে পারবেন:

iex> key = "hello"
"hello"
iex> %{key => "world"}
%{"hello" => "world"}

একই কী কে একাধিকবার ব্যবহার করলে, সর্বশেষ মানটি ব্যবহৃত হবে।

iex> %{:foo => "bar", :foo => "hello world"}
%{foo: "hello world"}

যদি শুধু অ্যাটম থাকে ম্যাপটির কী, তাহলে নীচের সিনট্যাক্সটি ব্যবহার করতে পারবেন:

iex> %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}

iex> %{foo: "bar", hello: "world"} == %{:foo => "bar", :hello => "world"}
true

ম্যাপের নিজস্ব সিনট্যাক্স রয়েছে আপডেট ও অ্যাক্সেসের জন্য যদি কী হয় অ্যাটম:

iex> map = %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
iex> %{map | foo: "baz"}
%{foo: "baz", hello: "world"}
iex> map.hello
"world"

ম্যাপের আরেকটা মজার গুণ হচ্ছে, একটি ম্যাপের ভ্যালু পরিবর্তন করার জন্য নিজস্ব সিনট্যাক্স আছে (দ্রষ্টব্য: এটি মূলত একটি নতুন ম্য়াপ তৈরী করে):

iex> map = %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
iex> %{map | foo: "baz"}
%{foo: "baz", hello: "world"}

বিঃদ্রঃ এই সিনট্যাক্স শুধুমাত্র তখনই কাজ করবে যখন কি টি ম্যাপে ইতমধ্যেই উপস্থিত আছে। যদি কি টি না থাকে, তাহলে KeyError রেইজ হবে।

নতুন কি তৈরী করতে হলে, Map.put/3 ব্যবহার করতে হবে।

iex> map = %{hello: "world"}
%{hello: "world"}
iex> %{map | foo: "baz"}
** (KeyError) key :foo not found in: %{hello: "world"}
    (stdlib) :maps.update(:foo, "baz", %{hello: "world"})
    (stdlib) erl_eval.erl:259: anonymous fn/2 in :erl_eval.expr/5
    (stdlib) lists.erl:1263: :lists.foldl/3
iex> Map.put(map, :foo, "baz")
%{foo: "baz", hello: "world"}
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!