fold
এর পার্থক্য কীভাবে বিভ্রান্তির ঘন ঘন উত্স বলে মনে হয়, তাই এখানে আরও সাধারণ সংক্ষিপ্ত বিবরণ দেওয়া হল:
[x1, x2, x3, x4 ... xn ]
কিছু ফাংশন f
এবং বীজের সাথে এন মানগুলির একটি তালিকা ভাঁজ করা বিবেচনা করুন z
।
foldl
হল:
- বাম সংঘবদ্ধ :
f ( ... (f (f (f (f z x1) x2) x3) x4) ...) xn
- লেজ পুনরাবৃত্তি : এটি তালিকার মাধ্যমে পুনরাবৃত্তি করে পরে মানটি তৈরি করে
- অলস : ফলাফল প্রয়োজন না হওয়া পর্যন্ত কিছুই মূল্যায়ন করা হয় না
- পিছনে :
foldl (flip (:)) []
একটি তালিকা বিপরীত।
foldr
হল:
- ডান সহযোগী :
f x1 (f x2 (f x3 (f x4 ... (f xn z) ... )))
- একটি যুক্তিতে পুনরাবৃত্তি: প্রতিটি পুনরাবৃত্তি
f
পরবর্তী মান এবং তালিকার বাকী ভাঁজ ফলাফলের জন্য প্রযোজ্য ।
- অলস : ফলাফল প্রয়োজন না হওয়া পর্যন্ত কিছুই মূল্যায়ন করা হয় না
- ফরোয়ার্ড :
foldr (:) []
অপরিবর্তিত তালিকা ফিরিয়ে দেয়।
একটা সামান্য সূক্ষ্ম এখানে বিন্দু যে ভ্রমণের লোককে কখনও কখনও: যেহেতু foldl
হয় পিছন প্রতিটি আবেদন f
যোগ করা হয় বাহিরে ফলাফলের; এবং কারণ এটি অলস , ফলাফলের প্রয়োজন না হওয়া পর্যন্ত কিছুই মূল্যায়ন করা হয় না। এর অর্থ হ'ল ফলাফলের যে কোনও অংশ গণনা করার জন্য, হাস্কেল প্রথমে নেস্টেড ফাংশন অ্যাপ্লিকেশনগুলির একটি এক্সপ্রেশন তৈরি করে পুরো তালিকার মাধ্যমে পুনরাবৃত্তি করে , তারপরে বাহ্যতমতম কার্যটি মূল্যায়ন করে, প্রয়োজনীয়তার সাথে তার আর্গুমেন্টগুলি মূল্যায়ন করে। যদি f
সর্বদা এটির প্রথম যুক্তি ব্যবহার করে, এর অর্থ হ্যাস্কেলকে আন্তঃতম শব্দটি পর্যন্ত সমস্ত উপায়ে পুনরাবৃত্তি করতে হবে, তারপরে প্রতিটি অ্যাপ্লিকেশনটির গণনার পিছনে পিছনে কাজ করুন f
।
এটি স্পষ্টতই কার্যকর লেজ-পুনরাবৃত্তি থেকে সর্বাধিক কার্যনির্বাহী প্রোগ্রামাররা জানেন এবং ভালোবাসেন cry
প্রকৃতপক্ষে, যদিও foldl
প্রযুক্তিগতভাবে পুচ্ছ-পুনরাবৃত্ত হয়, কারণ পুরো ফলাফল প্রকাশটি কোনও কিছুর মূল্যায়ন করার আগেই নির্মিত হয়েছিল, foldl
স্ট্যাকের ওভারফ্লো হতে পারে!
অন্যদিকে, বিবেচনা করুন foldr
। এটিও অলস, তবে এটি এগিয়েf
চলেছে বলে প্রতিটি প্রয়োগ ফলাফলের অভ্যন্তরে যুক্ত করা হয় । সুতরাং, ফলাফলটি গণনা করতে, হাস্কেল একটি একক ফাংশন অ্যাপ্লিকেশন তৈরি করে, যার দ্বিতীয় যুক্তিটি ভাঁজ তালিকার বাকি অংশ। যদি f
একটি ডাটা কন্সট্রাকটর, উদাহরণস্বরূপ - - তার দ্বিতীয় যুক্তি অলস ফল কী হবে বৃদ্ধিলাভ অলস এর নির্ণিত ভাঁজ প্রতিটি পদক্ষেপ সঙ্গে, শুধুমাত্র যখন ফলে চাহিদা এটা মূল্যায়ন করা হয় কিছু অংশ।
সুতরাং আমরা দেখতে পাই কেন foldr
কখনও কখনও অসীম তালিকায় কেন কাজ foldl
করে না: প্রাক্তনটি অলসভাবে একটি অসীম তালিকাটিকে অন্য একটি অলস অসীম ডেটা স্ট্রাকচারে রূপান্তর করতে পারে, অন্যদিকে ফলাফলটির কোনও অংশ উত্পন্ন করতে পরবর্তী তালিকাটিকে অবশ্যই পুরো তালিকাটি পরীক্ষা করতে হবে। অন্যদিকে, foldr
এমন একটি ফাংশন যা সাথে সাথে উভয় যুক্তির তত্ক্ষণাত প্রয়োজন, যেমন: (+)
কাজ করে (বা বরং কাজ করে না) অনেক বেশি পছন্দ করে foldl
, মূল্যায়নের আগে বিশাল অভিব্যক্তি তৈরি করে।
সুতরাং দুটি গুরুত্বপূর্ণ বিষয় লক্ষণীয়:
foldr
একটি অলস পুনরাবৃত্ত তথ্য কাঠামো অন্যটিতে রূপান্তর করতে পারে।
- অন্যথায়, অলস ভাঁজগুলি বৃহত বা অসীম তালিকায় স্ট্যাকের ওভারফ্লো দিয়ে ক্রাশ হবে।
আপনি লক্ষ্য করেছেন যে দেখে মনে হচ্ছে এটি foldr
সবকিছু foldl
করতে পারে আরও কিছু করতে পারে। এটা সত্য! আসলে, ভাঁজ প্রায় বেহুদা!
তবে যদি আমরা কোনও বৃহত (তবে অসীম নয়) তালিকায় ভাঁজ করে একটি অলস ফলাফল তৈরি করতে চাই তবে কী হবে? এর জন্য, আমরা একটি কঠোর ভাঁজ চাই , যা মানক গ্রন্থাগারগুলি যদিও সাফল্যের সাথে সরবরাহ করে :
foldl'
হল:
- বাম সংঘবদ্ধ :
f ( ... (f (f (f (f z x1) x2) x3) x4) ...) xn
- লেজ পুনরাবৃত্তি : এটি তালিকার মাধ্যমে পুনরাবৃত্তি করে পরে মানটি তৈরি করে
- কঠোর : প্রতিটি ফাংশন অ্যাপ্লিকেশনটি পাশাপাশি মূল্যায়ন করা হয়
- পিছনে :
foldl' (flip (:)) []
একটি তালিকা বিপরীত।
কারণ foldl'
হল কঠোর , গনা ফলাফলের জন্য Haskell হবে মূল্যায়নের f
পরিবর্তে বাম যুক্তি লেট প্রতিটি পদক্ষেপ, একটি বিশাল, unevaluated অভিব্যক্তি বাড়তে থাকে। এটি আমাদের স্বাভাবিক, কার্যকর লেজ পুনরাবৃত্তি দেয়! অন্য কথায়:
foldl'
দক্ষতার সাথে বড় তালিকা ভাঁজ করতে পারেন।
foldl'
অসীম তালিকায় একটি অসীম লুপে ঝুলবে (স্ট্যাকের উপচে পড়বে না)।
হাস্কেল উইকির একটি পৃষ্ঠাও এটি নিয়ে আলোচনা করেছে ।
foldr
ভাল চেয়েfoldl
মধ্যে Haskell, যখন বিপরীত সত্য Erlang (যা আমি আগে শিখেছি Haskell, )। যেহেতু Erlang অলস নয় এবং ফাংশন নেই curried , তাইfoldl
মধ্যে Erlang মত আচরণfoldl'
উপরে। এটি একটি দুর্দান্ত উত্তর! ভাল কাজ এবং ধন্যবাদ!