ইউ সংযুক্তকারী
আর্গুমেন্ট হিসাবে কোনও ক্রিয়াকলাপটি নিজের কাছে পাস করার মাধ্যমে কোনও ফাংশন তার নামের পরিবর্তে প্যারামিটার ব্যবহার করে পুনরাবৃত্তি করতে পারে! সুতরাং প্রদত্ত U
ফাংশনটিতে কমপক্ষে একটি প্যারামিটার থাকা উচিত যা ফাংশনটির সাথে আবদ্ধ হবে (নিজেই)।
নীচের উদাহরণে, আমাদের কোনও প্রস্থান শর্ত নেই, তাই স্ট্যাকের ওভারফ্লো না হওয়া পর্যন্ত আমরা অনির্দিষ্টকালের জন্য লুপ করব
const U = f => f (f) // call function f with itself as an argument
U (f => (console.log ('stack overflow imminent!'), U (f)))
আমরা বিভিন্ন কৌশল ব্যবহার করে অসীম পুনরাবৃত্তি থামাতে পারি। এখানে, আমি আমাদের বেনাম ফাংশনটি লিখব অন্য কোনও বেনামী ফাংশন যা ইনপুটটির জন্য অপেক্ষা করছে; এই ক্ষেত্রে, কিছু নম্বর। যখন কোনও সংখ্যা সরবরাহ করা হয়, এটি যদি 0 এর চেয়ে বেশি হয় তবে আমরা পুনরাবৃত্তি চালিয়ে যাব, অন্যথায় 0 ফিরে আসবে।
const log = x => (console.log (x), x)
const U = f => f (f)
// when our function is applied to itself, we get the inner function back
U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)
// returns: (x => x > 0 ? U (f) (log (x - 1)) : 0)
// where f is a reference to our outer function
// watch when we apply an argument to this function, eg 5
U (f => x => x > 0 ? U (f) (log (x - 1)) : 0) (5)
// 4 3 2 1 0
এখানে তাত্ক্ষণিকভাবে আপাত নয় যা হ'ল আমাদের ফাংশনটি যখন প্রথমে U
সংযোজক ব্যবহার করে নিজেকে প্রয়োগ করা হয় , এটি প্রথম ইনপুটটির জন্য অপেক্ষা করে একটি ফাংশন দেয়। যদি আমরা এটির একটি নাম দিয়ে থাকি তবে ল্যাম্বডাস (বেনামে ফাংশন) ব্যবহার করে কার্যকরভাবে পুনরাবৃত্ত ফাংশন তৈরি করতে পারি
const log = x => (console.log (x), x)
const U = f => f (f)
const countDown = U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)
countDown (5)
// 4 3 2 1 0
countDown (3)
// 2 1 0
কেবল এটি সরাসরি পুনরাবৃত্তি নয় - এমন একটি ফাংশন যা নিজের নাম ব্যবহার করে নিজেকে কল করে। আমাদের সংজ্ঞাটি countDown
তার দেহের অভ্যন্তরে নিজেকে উল্লেখ করে না এবং এখনও পুনরাবৃত্তি সম্ভব
// direct recursion references itself by name
const loop = (params) => {
if (condition)
return someValue
else
// loop references itself to recur...
return loop (adjustedParams)
}
// U combinator does not need a named reference
// no reference to `countDown` inside countDown's definition
const countDown = U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)
ইউ সংযোজক ব্যবহার করে কীভাবে বিদ্যমান ফাংশন থেকে স্ব-রেফারেন্স সরিয়ে ফেলা যায়
এখানে আমি আপনাকে দেখাব যে কীভাবে একটি পুনরাবৃত্ত ফাংশন নিতে হবে যা নিজের কাছে একটি রেফারেন্স ব্যবহার করে এবং এটি এমন একটি ফাংশনে পরিবর্তন করে যা ইউ সংযোজককে স্ব-রেফারেন্সের জায়গায় নিয়োগ দেয় to
const factorial = x =>
x === 0 ? 1 : x * factorial (x - 1)
console.log (factorial (5)) // 120
অভ্যন্তরীণ রেফারেন্সটি প্রতিস্থাপন করতে এখন ইউ সংযোগকারী ব্যবহার করে factorial
const U = f => f (f)
const factorial = U (f => x =>
x === 0 ? 1 : x * U (f) (x - 1))
console.log (factorial (5)) // 120
বেসিক রিপ্লেসমেন্ট প্যাটার্নটি এটি। একটি মানসিক নোট দিন, আমরা পরবর্তী বিভাগে অনুরূপ কৌশল ব্যবহার করব
// self reference recursion
const foo = x => ... foo (nextX) ...
// remove self reference with U combinator
const foo = U (f => x => ... U (f) (nextX) ...)
ওয়াই সংযুক্তকারী
সম্পর্কিত: ইউ এবং ওয়াই সংযুক্তকারীরা একটি আয়না উপমা ব্যবহার করে ব্যাখ্যা করেছিলেন
পূর্ববর্তী বিভাগে আমরা দেখেছি কীভাবে স্ব-রেফারেন্স পুনরাবৃত্তিটিকে একটি পুনরাবৃত্ত ফাংশনে রূপান্তর করতে হয় যা ইউ সংযোজক ব্যবহার করে একটি নামকৃত ফাংশনের উপর নির্ভর করে না। প্রথম আর্গুমেন্ট হিসাবে নিজেকে সর্বদা ফাংশনটি পাস করার কথা মনে রাখার সাথে সাথে বিরক্তি কিছুটা আছে। ঠিক আছে, ওয়াই-কম্বিনেটর ইউ-কম্বিনেটর তৈরি করে এবং সেই ক্লান্তিকর কিছুটা সরিয়ে দেয়। এটি একটি ভাল জিনিস কারণ জটিলতা অপসারণ / হ্রাস করা হ'ল আমাদের কার্য সম্পাদন করার প্রাথমিক কারণ
প্রথমে আসুন আমাদের নিজস্ব নিজস্ব-সংযুক্তকারী তৈরি করা যাক
// standard definition
const Y = f => f (Y (f))
// prevent immediate infinite recursion in applicative order language (JS)
const Y = f => f (x => Y (f) (x))
// remove reference to self using U combinator
const Y = U (h => f => f (x => U (h) (f) (x)))
এখন আমরা দেখতে পাচ্ছি কীভাবে এটির ব্যবহারটি ইউ-সংযুক্তকারীটির সাথে তুলনা করে। লক্ষ্য করুন, পুনরাবৃত্তি করার পরিবর্তে U (f)
আমরা কেবল কল করতে পারিf ()
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
Y (f => (console.log ('stack overflow imminent!'), f ()))
এখন আমি countDown
প্রোগ্রামটি ব্যবহার করে প্রদর্শন করব Y
- আপনি দেখতে পাবেন যে প্রোগ্রামগুলি প্রায় অভিন্ন তবে Y সংযোজক জিনিসগুলিকে কিছুটা পরিষ্কার রাখবেন
const log = x => (console.log (x), x)
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const countDown = Y (f => x => x > 0 ? f (log (x - 1)) : 0)
countDown (5)
// 4 3 2 1 0
countDown (3)
// 2 1 0
এবং এখন আমরা factorial
পাশাপাশি দেখতে পাবেন
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const factorial = Y (f => x =>
x === 0 ? 1 : x * f (x - 1))
console.log (factorial (5)) // 120
আপনি দেখতে পাচ্ছেন, f
নিজেই পুনরাবৃত্তি হওয়ার প্রক্রিয়া হয়ে ওঠে। পুনরাবৃত্তি করার জন্য, আমরা এটিকে একটি সাধারণ ফাংশনের মতো বলি। আমরা বিভিন্ন যুক্তি সহ এটি একাধিকবার কল করতে পারি এবং ফলাফলটি এখনও সঠিক হবে। এটি যেহেতু এটি একটি সাধারণ ফাংশন প্যারামিটার, তাই আমরা যা চাই তার নাম দিতে পারি যেমন recur
নীচে -
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const fibonacci = Y (recur => n =>
n < 2 ? n : recur (n - 1) + (n - 2))
console.log (fibonacci (10)) // 55
1 টিরও বেশি পরামিতি সহ ইউ এবং ওয়াই সংযুক্তকারী
উপরের উদাহরণগুলিতে, আমরা দেখেছি যে আমরা কীভাবে আমাদের গণনার "অবস্থা" র উপর নজর রাখতে একটি আর্গুমেন্ট লুপ করতে পারি এবং পাস করতে পারি। তবে আমাদের যদি অতিরিক্ত অবস্থার উপর নজর রাখা দরকার?
আমরা পারে একটি অ্যারের বা কিছু মত যৌগ ডেটা ব্যবহার ...
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const fibonacci = Y (f => ([a, b, x]) =>
x === 0 ? a : f ([b, a + b, x - 1]))
// starting with 0 and 1, generate the 7th number in the sequence
console.log (fibonacci ([0, 1, 7]))
// 0 1 1 2 3 5 8 13
তবে এটি খারাপ কারণ এটি অভ্যন্তরীণ অবস্থা (কাউন্টার a
এবং b
) প্রকাশ করছে। আমরা চাইলে fibonacci (7)
আমাদের উত্তরটি পেতে কেবল ফোন করতে পারলে ভাল লাগবে ।
ক্রেডিড ফাংশন (আনারি (1-প্যারামটার) ক্রিয়াকলাপ) সম্পর্কে আমরা যা জানি তা ব্যবহার করে, আমরা Y
যৌগিক ডেটা বা উন্নত ভাষার বৈশিষ্ট্যগুলিতে আমাদের সংজ্ঞাটি সংশোধন না করে বা নির্ভর করতে না পেরে সহজেই আমাদের লক্ষ্য অর্জন করতে পারি ।
fibonacci
নীচে নীচে সংজ্ঞা দেখুন। আমরা অবিলম্বে আবেদন করছি 0
এবং 1
যা যথাক্রমে আবদ্ধ a
এবং আবদ্ধ b
। এখন ফিবোনাচি কেবল শেষ যুক্তির সরবরাহের জন্য অপেক্ষা করছে যা আবদ্ধ হবে x
। যখন আমরা পুনরাবৃত্তি করি, আমাদের অবশ্যই কল করতে হবে f (a) (b) (x)
(নয় f (a,b,x)
) কারণ আমাদের ফাংশনটি ত্রিযুক্ত আকারে রয়েছে।
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const fibonacci = Y (f => a => b => x =>
x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
console.log (fibonacci (7))
// 0 1 1 2 3 5 8 13
এই ধরণের প্যাটার্নটি সমস্ত ধরণের কার্যকারিতা সংজ্ঞায়িত করতে কার্যকর হতে পারে। নীচে আমরা আরো দুটি ফাংশন ব্যবহার করে সংজ্ঞায়িত দেখতে পাবেন Y
combinator ( range
এবং reduce
) এবং একটি অমৌলিক reduce
, map
।
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const range = Y (f => acc => min => max =>
min > max ? acc : f ([...acc, min]) (min + 1) (max)) ([])
const reduce = Y (f => g => y => ([x,...xs]) =>
x === undefined ? y : f (g) (g (y) (x)) (xs))
const map = f =>
reduce (ys => x => [...ys, f (x)]) ([])
const add = x => y => x + y
const sq = x => x * x
console.log (range (-2) (2))
// [ -2, -1, 0, 1, 2 ]
console.log (reduce (add) (0) ([1,2,3,4]))
// 10
console.log (map (sq) ([1,2,3,4]))
// [ 1, 4, 9, 16 ]
এটি সমস্ত অনিয়মস ওএমজি
যেহেতু আমরা এখানে খাঁটি ফাংশন নিয়ে কাজ করছি, আমরা এর নাম সংজ্ঞায়নের জন্য যেকোন নামকৃত ফাংশনকে বিকল্প করতে পারি। যখন আমরা ফিবোনাচি নিই এবং নাম প্রকাশিত ফাংশনগুলি তাদের অভিব্যক্তি দিয়ে প্রতিস্থাপন করি তখন কী ঘটে তা দেখুন
/* const U = f => f (f)
*
* const Y = U (h => f => f (x => U (h) (f) (x)))
*
* const fibonacci = Y (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
*
*/
/*
* given fibonacci (7)
*
* replace fibonacci with its definition
* Y (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
*
* replace Y with its definition
* U (h => f => f (x => U (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
//
* replace U with its definition
* (f => f (f)) U (h => f => f (x => U (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
*/
let result =
(f => f (f)) (h => f => f (x => h (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
console.log (result) // 13
এবং সেখানে আপনার এটি রয়েছে - fibonacci (7)
অজ্ঞাতনামা ফাংশন ব্যতীত পুনরাবৃত্তভাবে গণনা করা