রেফারেনশিয়াল স্বচ্ছতা, কোনও ফাংশনকে উল্লেখ করা হয়, এটি নির্দেশ করে যে আপনি কেবলমাত্র তার যুক্তিগুলির মানগুলি দেখে সেই ফাংশনটি প্রয়োগের ফলাফলটি নির্ধারণ করতে পারেন। আপনি যে কোনও প্রোগ্রামিং ভাষায় উল্লেখযোগ্য স্বচ্ছ ফাংশন লিখতে পারেন, যেমন পাইথন, স্কিম, পাস্কেল, সি।
অন্যদিকে, বেশিরভাগ ভাষায় আপনি অ-রেফারেন্টালি স্বচ্ছ ফাংশনও লিখতে পারেন। উদাহরণস্বরূপ, এই পাইথন ফাংশন:
counter = 0
def foo(x):
global counter
counter += 1
return x + counter
প্রকৃতপক্ষে কলিং উল্লেখযোগ্যভাবে স্বচ্ছ নয়
foo(x) + foo(x)
এবং
2 * foo(x)
যে কোনও যুক্তির জন্য বিভিন্ন মান তৈরি করে x
। এর কারণ হ'ল ফাংশনটি একটি বৈশ্বিক পরিবর্তনশীল ব্যবহার করে এবং সংশোধন করে, সুতরাং প্রতিটি অনুরোধের ফলাফল এই পরিবর্তিত রাষ্ট্রের উপর নির্ভর করে, কেবলমাত্র ফাংশনের যুক্তিতে নয়।
Haskell,, একটি বিশুদ্ধরূপে কার্মিক ভাষা, কঠোরভাবে পৃথক অভিব্যক্তি মূল্যায়ন যা বিশুদ্ধ ফাংশন প্রয়োগ করা হয় এবং যা সবসময় referentially স্বচ্ছ, থেকে কর্ম সঞ্চালনের (বিশেষ মূল্যবোধের প্রক্রিয়াকরণ), যা referentially স্বচ্ছ নয়, অর্থাত্ একই কর্ম নির্বাহ প্রতিটি সময় একটি থাকতে পারে বিভিন্ন ফলাফল
সুতরাং, যে কোনও হাস্কেল ফাংশনের জন্য
f :: Int -> Int
এবং কোনও পূর্ণসংখ্যা x
, এটি সর্বদা সত্য
2 * (f x) == (f x) + (f x)
ক্রিয়াকলাপের উদাহরণ লাইব্রেরি ফাংশনের ফলাফল getLine
:
getLine :: IO String
অভিব্যক্তি মূল্যায়নের ফলস্বরূপ, প্রথমে এই ফাংশনটি (আসলে একটি ধ্রুবক) ধরণের বিশুদ্ধ মান উত্পাদন করে IO String
। এই ধরণের মানগুলি অন্য যেগুলির মতো মান: আপনি এগুলি চারপাশে পাস করতে পারেন, তাদেরকে ডেটা স্ট্রাকচারে রাখতে পারেন, বিশেষ ফাংশন ব্যবহার করে তাদের রচনা করতে পারেন। উদাহরণস্বরূপ আপনি এর মতো ক্রিয়াগুলির তালিকা তৈরি করতে পারেন:
[getLine, getLine] :: [IO String]
ক্রিয়াগুলি বিশেষ যা আপনি হাস্কেল রানটাইমকে লিখে দিয়ে তাদের সম্পাদন করতে বলতে পারেন:
main = <some action>
এই ক্ষেত্রে, যখন আপনার হাস্কেল প্রোগ্রাম শুরু হয়, রানটাইমটি আবদ্ধ ক্রিয়াটির মধ্য দিয়ে চলে main
এবং এটি সম্পাদন করে, সম্ভবত পার্শ্ব প্রতিক্রিয়া তৈরি করে। সুতরাং, অ্যাকশন এক্সিকিউশনটি উল্লেখযোগ্যভাবে স্বচ্ছ নয় কারণ একই সময় দুইবার একই ক্রিয়াকলাপ সম্পাদন করানো ইনপুট হিসাবে রানটাইম কী পায় তার উপর নির্ভর করে বিভিন্ন ফলাফল আনতে পারে।
হাস্কেলের টাইপ সিস্টেমকে ধন্যবাদ, একটি ক্রিয়া কখনই এমন প্রসঙ্গে ব্যবহার করা যাবে না যেখানে অন্য ধরণের প্রত্যাশিত হয় এবং বিপরীতে। সুতরাং, আপনি যদি কোনও স্ট্রিংয়ের দৈর্ঘ্য সন্ধান করতে চান তবে আপনি length
ফাংশনটি ব্যবহার করতে পারেন :
length "Hello"
ফিরে আসবে ৫. তবে আপনি যদি টার্মিনাল থেকে পড়া স্ট্রিংয়ের দৈর্ঘ্য সন্ধান করতে চান তবে আপনি লিখতে পারবেন না
length (getLine)
কারণ আপনি একটি টাইপ ত্রুটি পান: length
টাইপ তালিকার একটি ইনপুট প্রত্যাশা করে (এবং একটি স্ট্রিং প্রকৃতপক্ষে একটি তালিকা) তবে getLine
এটি টাইপের মান IO String
(একটি ক্রিয়া)। এই পদ্ধতিতে, টাইপ সিস্টেমটি নিশ্চিত করে যে কোনও ক্রিয়াকলাপের getLine
(যেমন কার্যকর ভাষা মূল ভাষার বাইরে পরিচালিত হয় এবং যা রেফারেন্টালি স্বচ্ছ হতে পারে) প্রকারের অ-অ্যাকশন মানের মধ্যে লুকানো যায় না Int
।
সম্পাদনা
এক্সিজ্ট প্রশ্নের উত্তর দেওয়ার জন্য, এখানে একটি ছোট হাসকল প্রোগ্রাম রয়েছে যা কনসোল থেকে একটি লাইন পড়ে এবং তার দৈর্ঘ্য মুদ্রণ করে।
main :: IO () -- The main program is an action of type IO ()
main = do
line <- getLine
putStrLn (show (length line))
প্রধান ক্রিয়ায় দুটি সাবজেক্ট থাকে যা ক্রমান্বয়ে সম্পাদিত হয়:
getline
ধরণের IO String
,
- দ্বিতীয়টি তার যুক্তি
putStrLn
অনুসারে টাইপ ফাংশন মূল্যায়ন করে নির্মিত হয় String -> IO ()
।
আরও স্পষ্টভাবে, দ্বিতীয় ক্রিয়াটি বিল্ট built
line
প্রথম ক্রিয়নের দ্বারা পড়া মানকে আবদ্ধ করা,
- খাঁটি ফাংশনগুলি
length
(পূর্ণসংখ্যা হিসাবে গণনা দৈর্ঘ্য) মূল্যায়ন এবং তারপরে show
(পূর্ণসংখ্যাকে একটি স্ট্রিংয়ে পরিণত করুন),
putStrLn
এর ফলাফলের সাথে ফাংশন প্রয়োগ করে ক্রিয়া তৈরি করা show
।
এই মুহুর্তে, দ্বিতীয় ক্রিয়াটি কার্যকর করা যেতে পারে। আপনি যদি "হ্যালো" টাইপ করেন তবে এটি "5" মুদ্রণ করবে।
দ্রষ্টব্য যে আপনি যদি <-
স্বরলিপিটি ব্যবহার করে কোনও ক্রিয়াকলাপের মধ্যে একটি মান পেয়ে থাকেন তবে আপনি কেবলমাত্র অন্য মানটির মধ্যে সেই মানটি ব্যবহার করতে পারেন, যেমন আপনি লিখতে পারবেন না:
main = do
line <- getLine
show (length line) -- Error:
-- Expected type: IO ()
-- Actual type: String
কারণ show (length line)
টাইপ রয়েছে String
যেখানে নোটেশনটির প্রয়োজন হয় যে কোনও ক্রিয়া ( getLine
টাইপ IO String
) এর পরে অন্য ক্রিয়া অনুসরণ করা উচিত (যেমন putStrLn (show (length line))
: টাইপ IO ()
)।
সম্পাদনা 2
রেফারেন্সিয়াল স্বচ্ছতার জার্গ ডব্লু মিট্টাগের সংজ্ঞা আমার চেয়ে বেশি সাধারণ (আমি তার উত্তরটিকে সমর্থন করেছি)। আমি একটি সীমাবদ্ধ সংজ্ঞা ব্যবহার করেছি কারণ প্রশ্নের উদাহরণটি ফাংশনের রিটার্ন মানকে কেন্দ্র করে এবং আমি এই দিকটি চিত্রিত করতে চেয়েছিলাম। তবে, আরটি সাধারণভাবে পুরো প্রোগ্রামটির অর্থকে বোঝায়, বিশ্বব্যাপী রাষ্ট্রের পরিবর্তন এবং একটি অভিব্যক্তি মূল্যায়নের ফলে পরিবেশের সাথে (আইও) ইন্টারঅ্যাকশন সহ। সুতরাং, একটি সঠিক, সাধারণ সংজ্ঞার জন্য, আপনার সেই উত্তরটি উল্লেখ করা উচিত।