Curry Function (কারি ফাংশন)

Omar Faruq
5 min readDec 22, 2023

--

বুঝতেই পারছেন আজ কথা বলবো curry function নিয়ে। curry function নিয়ে কথা বলার আগে Haskell curry এর সম্মানার্থে কিছু তথ্য না জানলেই নয়।

Haskel curry তার ফুল নাম হলো, “Haskell Brooks Curry” তিনি জন্মগ্রহণ করেন ১২ সেপ্টেম্বর ১৯০০ সালে। তিনি কোন computer scientist ছিলেন না। তিনি ছিলেন মূলত mathematician এবং logician তার আগ্রহের জায়গা ছিলো distinct philosophy of mathematics

অবশেষে,১ সেপ্টেম্বার ১৯৮২ সালে তিনি পরলোকগমন করেন।

‘ Curry ’ নামটি এসেছে Haskel curry-এর নাম অনুসারে।

এই ছিলো haskell curry সম্পর্কে কিছু তথ্য।

এখন আমরা Haskell curry-এর অবদান ধীরে ধীরে জানার চেষ্টা করবো ইনশাআল্লাহ।

Curry function বুঝার জন্য আমাদের কিছু প্রশ্নে উত্তর জানতে হবে। প্রশ্নগুলো হলো,

১। Curry function কি?

২। curry function এর সাথে JavaScript closer এর সম্পর্ক কি?

৩। partial function বলতে কি বুঝায়?

৪। একটি curry converter function কিভাবে লিখতে হয়?

৫। curry converter function এর shortcut way কি?

৬। curry function আমরা কেনো use করবো।

1. Definition of Curry function: A currying function is a higher-order function that transforms a function that takes multiple arguments into a series of functions, each taking a single argument. The result is a chain of partially applied functions.

curry function-এর সংগা থেকে জানতে পারলাম যে, curry function হলো series of function এবং এটি একটি higher-order-function ( HOC ) খানিকটা Code লিখে বুঝার চেষ্টা করি।

আগে একটি Normal function লিখি

function sum(a,b,c){
return a+b+c;
}
console.log(sum(5,5,5))

তাহলে, Haskell curry -এর কথা অনুযায়ী, function-এ অনেকগুলো argument থাকা যাবে না। তাহলে Haskell-এর নিয়োম অনুযায়ী উপরের Sum() function কে re-factor করি।

function sum(a){
return(b)=>{
return (c)=>{
return a+b+c;
}
}
}
console.log(sum(5)(5)(5))

এখন আপনি বলবেন, আগেইতো ভালো ছিলো, কম code লিখতে হতো। কিন্তু মি: হাসকেলের নিয়োম অনুযায়ী বেশি code লিখতে হচ্ছে। কিন্ত এখানে মনে রাখতে হবে যে, আমরা ছোট্ট একটা function দিয়ে বুঝার try করছি । অনেক বড় application-এর ক্ষেত্রে অনেক parameter থাকবে এবং অনেক complex কাজ করতে গেলে একদম হ-জ-ব-র-ল লেগে যাবে । সেখানে javascript-এর best practice থাকবে না, user experience ভাল হবে না, debug করতে গেলে মাথার চুল একটাও আস্ত থাকবে না। যারা SQA-Engineer তাদের life এলোমেলো করে দিবে। complex কাজের ক্ষেত্রে curry function-এর ব্যাপক পরিসরে use-case রয়েছে।

উপরের example দেখা যাচ্ছে যে function call করার সময়ে একাধিক argument দিতে হচ্ছে, এটাও ভাল practice না, তাহলে আমরা এভাবে লিখতে পারি

function  sum(a){
return function(b){
return function(c){
return a+b+c;
}
}
}
let result1 = sum(5); //--------(1)
let result2 = result1(5); //----(2)
let result3 = result2(5); // ---(3)

console.log(result3) // output: 15

এখন আপনি আবার বলবেন, আগেই ভাল ছিল, এক লাইনে output দেখতে পেতাম, এখন আর ৩ লাইন বারতি লিখতে হল। থামেন, don’t worry একটু পরেই বুজতে পারবেন। ভাল করে খেয়াল করেন, ভিতরে ভিতরে একটা ঘটনা ঘটে গেছে। কিছু কি বুজতে পারেন ? আসেন দেখি কি ঘটনা ঘটলো।

উপরে ৩ টি separate function আছে, ৩ টি ধাপে argument পাঠিয়েছি । first argument 5 যা result1-এর মধ্যে আছে এবং result-3-এর মধ্যে আছে তৃতীয় argument-এর মান , একটা আরেকটার উপর dependent কিন্তু প্রশ্ন হল, first argument-এর মান third argument মনে রাখছে কি করে ?

এইটা হচ্ছে JavaScript closer-এর জন্য। আসেন browser-এর console থেকে বুঝার try করি।

উপরের sum() function-এর result-2 কে console [১] করলে anonymous নামে একটি function দেখতে পাবো , একে সম্প্রসারন করলে দেখতে পাবো scope [২] তার মধ্যে Closer নামে কিছু একটা দেখতে পাবো। হাঁ, এটায় সেই কাঙ্খিত Closer । এর মধ্যে ২ টি নাম্বার (৬, ৫) দেখা যাচ্ছে । এটায় হল সেই result1 এবং result2 এর value

আসা করি এতটুকও আমরা বুঝতে পারছি, এখন প্রশ্ন হল, আমরা argument গুলো ৩ ধাপে কেন পাঠালাম ? এর ফজিলত কি ? এতে আমি কি Benefit পেলাম ?

এটা বুঝার জন্য একটা situation consider করেন, ধরেন Daraz তাদের 11.11 camping করতে ২০% discount দিচ্ছে, তার মানে এই ২০% constant value যা কোন একটা জায়গায় সেট করে রাখা হয়েছে এবং প্রতিটা পণ্যের দাম ঐ যে constant ২০% মানকে Re-use কর নতুন দাম calculate করছে । বাকিটা আমরা coding example দিয়ে বুঝি ।

function discount(price, dis){
return price-price*dis
}
let customer1 = discount(600, 0.2)
let customer2 = discount(1200, 0.2)
console.log(customer2)
// 0.2 is repeated value

তাহলে repeated value দূর করতে উপরের কোড re-factor করে এভহাবে লিখি

function discount(dis){
return (price)=>{
return price-price*dis;
}
}
let twyntiPercentDiscount = discount(0.2); // partial function
let customer1 = twyntiPercentDiscount(600);
console.log(customer1); //output: 480
let customer2 = twyntiPercentDiscount(1200);
console.log(customer2); //output: 960

এখানে partial function নিয়ে আল্পকিছু বলে রাখি , partial function হল curry function -এর মধ্যে থাকা re-usable function উপরের কডে cutomer1, customer2 হল partial function । সুতরাং আমি বলতে পারি , অনেকগুলো partial function — এর সমষ্টি হল Curry function.

উপরের কোড good pattern maintain করছে বটে কিন্তু, একটা problem রয়ে গেছে । ধরেন, আপনার একটা বড় application-এ ১০০ টি function আছে , আপনি কি প্রতিবার এইভাবে curry function রুপান্তর করবেন ? এটা কি কোন যুক্তিসম্মত কাজ হল ? না হল না । তাহলে উপায় কি ? বলছি,

যদি আপনার কাছে এমন একটা curry converter helper function থাকত, তাহলে ক্যামন হতো, যেখানে একটি Normal function input দিব, আর converter return করবে curried version । automation এর একটা fill পাওয়া যেত । আসেন, আমরা একটা curry — converter function বানাই…

function normalToCurry(normal_function){
return function curried(...args){
if(args.length >= normal_function.length){
return normal_function.apply(this, args);
}else{
return function (...args2){
return curried.apply(this, args.concat(args2));
}
}
}
}
function sum (a,b,c){
return a+b+c;
}
let curriedSum = normalToCurry(sum);
console.log(curriedSum(1,2,3))
console.log(curriedSum(1)(2,4))
console.log(curriedSum(1)(2)(10))

এখন মনে একটু স্বস্তি পাচ্ছি , Converter function আছে আর কি লাগে । তবে আপনাদের জন্য একটি good news আছে । তাহলো shortcut way, ১) lodash package ব্যবহার করে এবং ২) JavaScript ES6 syntax ব্যবহার করে।

প্রথমে, আমরা JavaScript ES6-এর মাধ্যমে কিভাবে করতে হয় তা দেখি …

const sum = (a)=>(b)=>(c)=> a+b+c;
console.log(sum(5)(6)(8)) //output: 19

এই syntax অনুসারে আর অনেক use-case আছে, সেগুলো নিয়ে self explore করলে বুঝা যাবে।

এরপর আমরা third party Package ব্যাবহার করে same কাজটি কিভাবে করতে হয় তা দেখবো। প্রথমে আমরা ‘lodash’ নামক একটি Package install করবো। এরপর curry function -এর পরিবর্তে _.curry

ব্যবহার করলেই কাজ শেষ। এই জন্য curry converter function টি ব্যাবহার করে বুঝবো।

function sum (a,b,c){
return a+b+c;
}
let curriedSum = _.curry(sum); // _.curry come from loadsh
console.log(curriedSum(1,2,3))
console.log(curriedSum(1)(2,4))
console.log(curriedSum(1)(2)(10))

আলোচনা শেষ হয়েও জেন শেষ হল না, তাই শেষ কথা বলতে কিছু নাই, তবুও curry function নিয়ে একটা clear ধারনা দেয়ার চেষ্টা করেছি । এখনও মনের মধ্যে একটি প্রশ্ন উকি দিচ্ছে, তা হল curry function আমরা কেনো use করবো ? এই প্রশ্নের উত্তর জেনে আজকের আলোচনা শেষ করবো।

curry function use করার বেস কিছু সুবিধা আছে ,

১) HOC (Higher order component) বানাতে help করে।

২) Useful Building Modular এবং re-usable code লিখতে help করে।

৩) Same variable অনেকবার লিখতে হয়না ।

৪) Code অনেক বেশি Human Readable থাকে, তাই debugging করতে সুবিধা হয়।

৫) SQA — engineer এর Test-case লিখতে সুবিধা হয়।

--

--