জটিলতম অংশটি লুপ। আমাদের এটি দিয়ে শুরু করা যাক। একটি লুপ সাধারণত একক ফাংশন দিয়ে পুনরাবৃত্তি প্রকাশ করে ক্রিয়ামূলক শৈলীতে রূপান্তরিত হয়। একটি পুনরাবৃত্তি হ'ল লুপ ভেরিয়েবলের রূপান্তর।
এখানে একটি সাধারণ লুপের কার্যকরী বাস্তবায়ন:
loop : v -> (v -> v) -> (v -> Bool) -> v
loop init iter cond_to_cont =
if cond_to_cont init
then loop (iter init) iter cond
else init
এটি লাগে (লুপ ভেরিয়েবলের একটি প্রাথমিক মান, ফাংশন যা একটি একক পুনরাবৃত্তি [লুপ ভেরিয়েবলের উপরে প্রকাশ করে)) (লুপটি চালিয়ে যাওয়ার শর্ত)।
আপনার উদাহরণটি অ্যারেতে একটি লুপ ব্যবহার করে যা ভেঙে যায়। আপনার অপরিহার্য ভাষায় এই ক্ষমতাটি ভাষাতেই বেকড। কার্যকরী প্রোগ্রামিংয়ে এ জাতীয় ক্ষমতা সাধারণত গ্রন্থাগার পর্যায়ে প্রয়োগ করা হয়। এখানে একটি সম্ভাব্য বাস্তবায়ন
module Array (foldlc) where
foldlc : v -> (v -> e -> v) -> (v -> Bool) -> Array e -> v
foldlc init iter cond_to_cont arr =
loop
(init, 0)
(λ (val, next_pos) -> (iter val (at next_pos arr), next_pos + 1))
(λ (val, next_pos) -> and (cond_to_cont val) (next_pos < size arr))
এটা :
আমি একটি ((ভাল, নেক্সট_পোস)) জোড়া ব্যবহার করব যা লুপ ভেরিয়েবলের বাইরে দৃশ্যমান এবং অ্যারেতে অবস্থান রাখবে যা এই ফাংশনটি আড়াল করে।
সাধারণ লুপের তুলনায় পুনরাবৃত্তি ফাংশনটি কিছুটা জটিল, এই সংস্করণটি অ্যারের বর্তমান উপাদানটি ব্যবহার সম্ভব করে। [এটি তরকারিযুক্ত আকারে রয়েছে।]
এই জাতীয় ফাংশনগুলির নাম সাধারণত "ভাঁজ" করা হয়।
অ্যারের উপাদানগুলির সংचयটি বাম-সহযোগী পদ্ধতিতে সম্পন্ন হয়েছে তা বোঝাতে আমি নামে একটি "এল" রেখেছি; নিম্ন থেকে উচ্চ সূচক পর্যন্ত কোনও অ্যারে পুনরুক্ত করার জন্য অপরিহার্য প্রোগ্রামিং ভাষার অভ্যাসের অনুকরণ করতে।
আমি নামের মধ্যে একটি "সি" রেখেছি যে ফোল্ডের এই সংস্করণটি এমন একটি শর্ত নেয় যা কখন এবং কখন লুপটি বন্ধ করা উচিত তা নিয়ন্ত্রণ করে।
অবশ্যই এই ধরনের ইউটিলিটি ফাংশনগুলি সম্ভবত কার্যকরী প্রোগ্রামিং ভাষার সাথে ব্যবহৃত বেস লাইব্রেরিতে সহজলভ্য হতে পারে। আমি এখানে তাদের প্রদর্শনের জন্য লিখেছি।
অত্যাবশ্যকীয় ক্ষেত্রে আমাদের কাছে সেই সমস্ত সরঞ্জাম রয়েছে যা ভাষায় রয়েছে, আমরা আপনার উদাহরণের নির্দিষ্ট কার্যকারিতাটি বাস্তবায়িত করতে পারি to
আপনার লুপের পরিবর্তনশীলটি একটি জুড়ি ('উত্তর', একটি বুলিয়ান যা চালিয়ে যাওয়া উচিত কিনা তা এনকোড করে)।
iter : (Int, Bool) -> Int -> (Int, Bool)
iter (answer, cont) collection_element =
let new_answer = answer + collection_element
in case new_answer of
10 -> (new_answer, false)
150 -> (new_answer + 100, true)
_ -> (new_answer, true)
মনে রাখবেন যে আমি একটি নতুন "ভেরিয়েবল" 'new_answer' ব্যবহার করেছি। এটি কারণ ক্রিয়ামূলক প্রোগ্রামিংয়ে আমি ইতিমধ্যে আরম্ভকৃত "ভেরিয়েবল" এর মান পরিবর্তন করতে পারি না। আমি পারফরম্যান্স নিয়ে চিন্তিত নই, সংকলকটি যদি আরও দক্ষ বলে মনে করে তবে লাইফ-টাইম বিশ্লেষণের মাধ্যমে 'নতুন_উত্তরকারী' এর জন্য 'উত্তর' এর স্মৃতি পুনরায় ব্যবহার করতে পারে।
আমাদের লুপ ফাংশনটিতে এটি ইতিপূর্বে বিকাশ করা হয়েছে:
doSomeCalc :: Array Int -> Int
doSomeCalc arr = fst (Array.foldlc (0, true) iter snd arr)
"অ্যারে" এখানে মডিউলটির নাম যা রফতানি ফোল্ডেলসিটি হয়।
"মুষ্টি", "সেকেন্ড" ফাংশনগুলির জন্য দাঁড়ায় যা তার জোড়া প্যারামিটারের প্রথম, দ্বিতীয় উপাদানটি দেয় returns
fst : (x, y) -> x
snd : (x, y) -> y
এই ক্ষেত্রে "বিন্দু মুক্ত" শৈলী doSomeCalc বাস্তবায়নের পাঠযোগ্যতা বৃদ্ধি করে:
doSomeCalc = Array.foldlc (0, true) iter snd >>> fst
(>>>) হল ফাংশন কম্পোজিশন: (>>>) : (a -> b) -> (b -> c) -> (a -> c)
এটি উপরের মতোই, সংজ্ঞায়িত সমীকরণের উভয় দিক থেকে কেবল "আরর" প্যারামিটারটি বাকী রয়েছে।
একটি শেষ জিনিস: কেস (অ্যারে == নাল) জন্য পরীক্ষা করা। উন্নততর নকশাকৃত প্রোগ্রামিং ভাষাগুলিতে, তবে কিছু প্রাথমিক শৃঙ্খলাযুক্ত খারাপভাবে নকশাকৃত ভাষাগুলিতেও এটি অ-অস্তিত্ব প্রকাশ করার জন্য একটি optionচ্ছিক প্রকার ব্যবহার করে । এটি কার্যকরী প্রোগ্রামিংয়ের সাথে খুব বেশি সম্পর্ক রাখে না, যা সম্পর্কে প্রশ্নটি শেষ পর্যন্ত হয়, সুতরাং আমি এটি নিয়ে কাজ করি না।
break
এবংreturn answer
একটি দ্বারা প্রতিস্থাপিত হতে পারেreturn
লুপ ভিতরে। এফপিতে আপনি ধারাবাহিকতা ব্যবহার করে এই প্রারম্ভিক রিটার্নটি