ঠিক আছে!
নীচের কোডটি ES6 সিনট্যাক্স ব্যবহার করে লেখা হয়েছে তবে কেবল সহজেই ES5 বা তার চেয়েও কম লেখা যেতে পারে। ES6 কোনও "x বার লুপ করার পদ্ধতি" তৈরি করার প্রয়োজন হয় না
যদি কলব্যাকে আপনার পুনরুক্তি প্রয়োজন না হয় তবে এটি সর্বাধিক সাধারণ বাস্তবায়ন
const times = x => f => {
if (x > 0) {
f()
times (x - 1) (f)
}
}
// use it
times (3) (() => console.log('hi'))
// or define intermediate functions for reuse
let twice = times (2)
// twice the power !
twice (() => console.log('double vision'))
যদি আপনার পুনরুক্তি প্রয়োজন হয় , আপনি আপনার জন্য পুনরাবৃত্তি করতে একটি কাউন্টার প্যারামিটার সহ একটি নামকৃত অভ্যন্তরীণ ফাংশন ব্যবহার করতে পারেন
const times = n => f => {
let iter = i => {
if (i === n) return
f (i)
iter (i + 1)
}
return iter (0)
}
times (3) (i => console.log(i, 'hi'))
আপনি যদি আরও কিছু শিখতে পছন্দ না করেন তবে এখানে পড়া বন্ধ করুন ...
তবে সেগুলি সম্পর্কে কিছু মনে করা উচিত ...
- একক শাখার
if
বিবৃতি কুৎসিত - অন্য শাখায় কী ঘটে?
- ফাংশন বডিগুলিতে একাধিক বিবৃতি / অভিব্যক্তি - প্রক্রিয়া উদ্বেগগুলি মিশ্রিত হচ্ছে?
- স্পষ্টভাবে প্রত্যাবর্তন
undefined
- অপরিষ্কার ইঙ্গিত, পার্শ্ব-প্রভাব কার্যকারিতা
"এর চেয়ে ভাল উপায় আর নেই?"
এখানে. আসুন প্রথমে আমাদের প্রাথমিক প্রয়োগটি আবার ঘুরে দেখি
// times :: Int -> (void -> void) -> void
const times = x => f => {
if (x > 0) {
f() // has to be side-effecting function
times (x - 1) (f)
}
}
অবশ্যই, এটি সহজ, তবে লক্ষ্য করুন যে আমরা কীভাবে কল করি f()
এবং এটি দিয়ে কিছু না করি। এটি সত্যিই এমন এক ধরণের ক্রিয়াকে সীমাবদ্ধ করে যা আমরা একাধিকবার পুনরাবৃত্তি করতে পারি। আমাদের কাছে পুনরুক্তি উপলব্ধ থাকলেও, f(i)
এটি আরও বহুমুখী নয়।
যদি আমরা আরও ভাল ধরণের ফাংশন পুনরাবৃত্তি পদ্ধতি দিয়ে শুরু করি তবে কী হবে? হয়ত এমন কিছু যা ইনপুট এবং আউটপুটটির আরও ভাল ব্যবহার করে।
জেনেরিক ফাংশন পুনরাবৃত্তি
// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
if (n > 0)
return repeat (n - 1) (f) (f (x))
else
return x
}
// power :: Int -> Int -> Int
const power = base => exp => {
// repeat <exp> times, <base> * <x>, starting with 1
return repeat (exp) (x => base * x) (1)
}
console.log(power (2) (8))
// => 256
উপরে, আমরা একটি জেনেরিক সংজ্ঞায়িত করেছি repeat
ফাংশন যা অতিরিক্ত ইনপুট নেয় যা একক ফাংশনের পুনরাবৃত্তি প্রয়োগ শুরু করতে ব্যবহৃত হয়।
// repeat 3 times, the function f, starting with x ...
var result = repeat (3) (f) (x)
// is the same as ...
var result = f(f(f(x)))
বাস্তবায়নকারী times
সঙ্গেrepeat
আচ্ছা এটি এখন সহজ; প্রায় সব কাজ ইতিমধ্যে সম্পন্ন হয়েছে।
// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
if (n > 0)
return repeat (n - 1) (f) (f (x))
else
return x
}
// times :: Int -> (Int -> Int) -> Int
const times = n=> f=>
repeat (n) (i => (f(i), i + 1)) (0)
// use it
times (3) (i => console.log(i, 'hi'))
যেহেতু আমাদের ফাংশনটি i
একটি ইনপুট হিসাবে নেয় এবং ফিরে আসেi + 1
, এটি কার্যকরভাবে আমাদের পুনরাবৃত্তকারী হিসাবে কাজ করে যা আমরা f
প্রতিটি সময়কে পাস করি ।
আমরা আমাদের বুলেট তালিকাগুলির তালিকাও ঠিক করেছি
- আর কুরুচিপূর্ণ একক শাখা নেই
if
বিবৃতি নেই
- একক-প্রকাশের দেহগুলি সুন্দরভাবে বিচ্ছিন্ন উদ্বেগগুলি নির্দেশ করে
- আর অকেজো, স্পষ্টভাবে ফিরে আসেনি
undefined
জাভাস্ক্রিপ্ট কমা অপারেটর,
শেষ উদাহরণটি কীভাবে কাজ করছে তা দেখতে আপনার যদি সমস্যা হয় তবে এটি জাভাস্ক্রিপ্টের প্রাচীনতম যুদ্ধ অক্ষগুলির একটি সম্পর্কে আপনার সচেতনতার উপর নির্ভর করে; কমা অপারেটর - সংক্ষিপ্ত, এটা এক্সপ্রেশন বাঁ দিক থেকে ডানদিকে মূল্যায়ণ এবং ফেরৎ গত মূল্যায়ন মত প্রকাশের মান
(expr1 :: a, expr2 :: b, expr3 :: c) :: c
আমাদের উপরের উদাহরণে, আমি ব্যবহার করছি
(i => (f(i), i + 1))
এটি কেবল লেখার একটি সংক্ষিপ্ত উপায়
(i => { f(i); return i + 1 })
টেল কল অপটিমাইজেশন
পুনরাবৃত্তিমূলক বাস্তবায়ন যেমন সেক্সি, এই মুহুর্তে জাভাস্ক্রিপ্ট ভিএম না থাকায় তাদের সুপারিশ করা আমার পক্ষে দায়িত্বজ্ঞানজনক হবে না আমি যথাযথ লেজ কল নির্মূলের পক্ষে সমর্থন করতে পারে না - বাবেল এটি প্রতিস্থাপন করতে ব্যবহৃত হয়েছিল, তবে এটি "ভাঙ্গা; পুনরায় প্রতিস্থাপন করবে" "এক বছরেরও বেশি সময় ধরে স্ট্যাটাস।
repeat (1e6) (someFunc) (x)
// => RangeError: Maximum call stack size exceeded
এর মতো, আমাদের বাস্তবায়নের পুনর্বিবেচনা করা উচিত repeat
এটিকে স্ট্যাক-নিরাপদ করতে ।
নিচের কোড আছে চপল বিকল্পগুলি ব্যবহার n
এবং x
কিন্তু মনে রাখবেন যে সমস্ত পরিব্যক্তি থেকে অনূদিত হয় repeat
কোন রাষ্ট্র পরিবর্তনগুলি (পরিব্যক্তি) ফাংশনের বাইরে থেকে দৃশ্যমান - ফাংশন
// repeat :: Int -> (a -> a) -> (a -> a)
const repeat = n => f => x =>
{
let m = 0, acc = x
while (m < n)
(m = m + 1, acc = f (acc))
return acc
}
// inc :: Int -> Int
const inc = x =>
x + 1
console.log (repeat (1e8) (inc) (0))
// 100000000
এটি আপনার প্রচুর বক্তব্য রাখবে "তবে এটি কার্যকরী নয়!" - আমি জানি, আরাম করুন। আমরা খাঁটি অভিব্যক্তি ব্যবহার করে ধ্রুবক-স্থান লুপিংয়ের জন্য ক্লোজার-স্টাইল loop
/ recur
ইন্টারফেস প্রয়োগ করতে পারি ; এগুলোর একটাও নাwhile
জিনিস কিছুই।
এখানে আমরা while
আমাদের loop
ফাংশনটি বিমূর্ত করি - recur
লুপটি চালিয়ে যাওয়ার জন্য এটি একটি বিশেষ ধরণের সন্ধান করে। যখন কোনও অ- recur
টাইপের সম্মুখীন হয়, লুপটি সমাপ্ত হয় এবং গণনার ফলাফল ফিরে আসে
const recur = (...args) =>
({ type: recur, args })
const loop = f =>
{
let acc = f ()
while (acc.type === recur)
acc = f (...acc.args)
return acc
}
const repeat = $n => f => x =>
loop ((n = $n, acc = x) =>
n === 0
? acc
: recur (n - 1, f (acc)))
const inc = x =>
x + 1
const fibonacci = $n =>
loop ((n = $n, a = 0, b = 1) =>
n === 0
? a
: recur (n - 1, b, a + b))
console.log (repeat (1e7) (inc) (0)) // 10000000
console.log (fibonacci (100)) // 354224848179262000000