Funksional dasturlash usullari: Currying tushunchasi va qisman qo'llash (partial application), universal curry() funksiyasi, Function Composition (compose vs pipe) va ma'lumotlar oqimi.
Bu bobda funksional dasturlashning ikkita kuchli texnikasi — Currying va Function Compositionni o'rganamiz. Ular Chapter 12 (Closures) va Chapter 14 (Higher-Order Functions) bilimlariga asoslanadi.
Currying — bir nechta argument qabul qiluvchi functionni, har safar bitta argument qabul qiluvchi function'lar zanjiriga aylantirish texnikasi.
☕️ Currying'ni bosqichma-bosqich buyurtma berishga o'xshating: kofe hajmini tanlaysiz, keyin turini tanlaysiz, keyin shakar miqdorini tanlaysiz — har bir tanlov alohida "qadam", va faqat barcha tanlovlar tugagach, yakuniy kofe (natija) tayyor bo'ladi.
script.jsJavaScript// Oddiy functionfunction add(a, b, c) {return a + b + c;}console.log(add(1, 2, 3)); // 6// Curried functionfunction curriedAdd(a) {return function (b) {return function (c) {return a + b + c;};};}console.log(curriedAdd(1)(2)(3)); // 6
curriedAdd(1) — b argumentini kutayotgan yangi function qaytaradi. curriedAdd(1)(2) — c argumentini kutayotgan yana bir function qaytaradi. Faqat uchinchi chaqiruv ((3)) — yakuniy natijani beradi.
🔗 Connection
Bu — Chapter 12'da o'rgangan createMultiplier misolining kengaytirilgan ko'rinishi: har bir ichki function — closure orqali tashqi argumentlarni "eslab qoladi".
Currying'ning asosiy foydasi — qisman qo'llash (partial application): ba'zi argumentlarni oldindan "belgilab qo'yib", keyinroq faqat qolganlarini berish.
script.jsJavaScriptfunction multiply(a) {return function (b) {return a * b;};}let double = multiply(2);let triple = multiply(3);console.log(double(5)); // 10console.log(triple(5)); // 15
multiply(2) — a = 2ni "eslab qolgan", faqat bni kutayotgan yangi function (double) yaratadi. Bu — Chapter 14'da ko'rgan createMultiplier bilan bir xil, faqat endi buni "Currying" atamasi bilan tushunayapmiz.
script.jsJavaScriptfunction log(level) {return function (message) {console.log(`[${level.toUpperCase()}] ${message}`);};}let logError = log("error");let logInfo = log("info");logError("Fayl topilmadi"); // "[ERROR] Fayl topilmadi"logInfo("Dastur ishga tushdi"); // "[INFO] Dastur ishga tushdi"
💡 Key Idea
Currying — bir xil "asosiy mantiq"ga ega, lekin turli "sozlamalar" bilan ishlaydigan function'larni yaratishning ixcham usuli.
Har safar qo'lda ichma-ich function yozish o'rniga, istalgan functionni avtomatik "curry qiladigan" umumiy HOF yozish mumkin.
script.jsJavaScriptfunction curry(func) {return function curried(...args) {if (args.length >= func.length) {return func.apply(this, args);} else {return function (...moreArgs) {return curried.apply(this, args.concat(moreArgs));};}};}function sum(a, b, c) {return a + b + c;}let curriedSum = curry(sum);console.log(curriedSum(1, 2, 3)); // 6 — barchasi birgaconsole.log(curriedSum(1)(2)(3)); // 6 — birma-birconsole.log(curriedSum(1, 2)(3)); // 6 — aralash
func.length — Chapter 6'dan ma'lum: bu function e'lon qilingandagi parametrlar sonini bildiradi (bu — function'ning maxsus propertysi).args.length) — kerakli sondan (func.length) kam bo'lsa, yana argument kutuvchi yangi function qaytariladi.func chaqiriladi.🔥 Important
Bu — Currying'ning eng moslashuvchan shakli: u argumentlarni istalgan tartibda (birma-bir, guruh-guruh, yoki barchasini birga) qabul qilishga imkon beradi.
Function Composition — bir nechta kichik function'ni birlashtirib, ularning natijasi ketma-ket bir-biriga "uzatiladigan" yagona, kattaroq function yaratish.
🏭 Function Composition — bu ishlab chiqarish konveyeri: xomashyo birinchi stansiyadan o'tadi, uning natijasi ikkinchi stansiyaga uzatiladi, va hokazo — har bir stansiya oldingisining natijasi ustida ishlaydi.
script.jsJavaScriptfunction double(x) {return x * 2;}function increment(x) {return x + 1;}function square(x) {return x * x;}let result = square(increment(double(5)));// double(5) = 10 → increment(10) = 11 → square(11) = 121console.log(result); // 121
Muammo: square(increment(double(5))) — o'qish uchun "ichkaridan tashqariga" o'qilishi kerak, bu tabiiy o'qish yo'nalishiga (chapdan o'ngga) zid.
script.jsJavaScriptfunction compose(...funcs) {return function (initialValue) {return funcs.reduceRight((acc, func) => func(acc), initialValue);};}let transform = compose(square, increment, double);console.log(transform(5)); // 121 (xuddi yuqoridagi kabi)
compose(square, increment, double) — 3 ta functionni argument sifatida qabul qiladi (Chapter 6'dagi rest parameters).reduceRight() — Chapter 15'dagi reduce()ga o'xshaydi, lekin o'ngdan chapga ishlaydi.5) — eng o'ngdagi function'dan (double) boshlab, ketma-ket chapga qarab ishlov beriladi: double(5)=10 → increment(10)=11 → square(11)=121.🔗 Connection
Bu — Chapter 15'da o'rgangan reduce()ning ilg'or, amaliy qo'llanilishi: bir nechta function'ni "yig'ib", bitta yakuniy natijaga keltirish.
script.jsJavaScriptfunction pipe(...funcs) {return function (initialValue) {return funcs.reduce((acc, func) => func(acc), initialValue);};}let transform2 = pipe(double, increment, square);console.log(transform2(5)); // 121 — xuddi shu natija, lekin O'QISH TARTIBI chapdan o'ngga!
pipe() — oddiy reduce() (chapdan o'ngga) ishlatadi, shuning uchun function'lar yozilgan tartibda (chapdan o'ngga) bajariladi — bu ko'pchilik uchun tabiiyroq o'qiladi.
⚠️ Common Mistake
compose va pipeni farqlash — ular bir xil natija berishi mumkin, lekin function'larning yozilish tartibi (o'ngdan chapga vs chapdan o'ngga) farq qiladi. Loyihada qaysi biri ishlatilishidan qat'iy nazar, jamoa ichida bir xil konventsiyaga rioya qilish muhim.
Task:
curriedMultiply(a)(b)(c) — uch sonni ko'paytiruvchi curried function yozing (qo'lda, ichma-ich function orqali, Chapter 45.1'dagi kabi).
Required Concepts:
function curriedMultiply(a) { return b => c => a * b * c; }Task:
Chapter 45.3'dagi umumiy curry() functionidan foydalanib, volume(length, width, height) (uchta o'lchamning ko'paytmasi) functionini curry qiling va uni turli usullarda (volume(2)(3)(4), volume(2, 3)(4), volume(2, 3, 4)) chaqirib sinab ko'ring.
Required Concepts:
curry()Task:
Chapter 45.4'dagi pipe() functionidan foydalanib, matnni qayta ishlovchi 3 ta kichik function yarating: trim, toLowerCase, va capitalize (birinchi harfni katta qiladigan). Ularni pipe() orqali birlashtirib, " hello World " matnini "Hello world" ga aylantiring.
Required Concepts:
pipe()capitalize function: s => s.charAt(0).toUpperCase() + s.slice(1)script.jsJavaScriptfunction curry(func) {return function curried(...args) {if (args.length >= func.length) {return func.apply(this, args);}return (...moreArgs) => curried.apply(this, args.concat(moreArgs));};}function sum3(a, b, c) {return a + b + c;}let curried = curry(sum3);console.log(curried(10)(20)(30));console.log(curried(10, 20)(30));
🧠 Think first! Javobni ko'rishdan oldin kamida 30 soniya o'ylang.
<details> <summary>Answer</summary> 60 60Why?
curry() — argumentlarning qanday guruhlarga bo'lib berilishidan (birma-bir yoki guruh-guruh) qat'i nazar, func.length (3)ga yetguncha ularni to'playveradi. Ikkala holatda ham, jami 3 ta argument (10, 20, 30) yig'ilgach, sum3(10, 20, 30) chaqiriladi va natija — 60.
Quyidagi kodda muammo bor:
script.jsJavaScriptfunction compose(...funcs) {return function (value) {return funcs.reduce((acc, func) => func(acc), value);};}let addOne = x => x + 1;let double = x => x * 2;let result = compose(addOne, double)(5);console.log(result); // Dasturchi 11 kutgan (5*2=10, +1=11), lekin 12 chiqadi
Your Task:
Yechim — reduceRight() ishlatish (haqiqiy compose uchun):
</details>script.jsJavaScriptfunction compose(...funcs) {return function (value) {return funcs.reduceRight((acc, func) => func(acc), value);};}let result = compose(addOne, double)(5);// double(5) = 10, keyin addOne(10) = 11console.log(result); // 11
compose() — o'ngdan chapga, pipe() — chapdan o'ngga ishlaydi.func.length — function'ning kutilayotgan parametrlar sonini avtomatik aniqlash uchun ishlatilishi mumkin.script.jsJavaScript// Curryfunction curry(fn) {return function curried(...args) {return args.length >= fn.length? fn.apply(this, args): (...more) => curried.apply(this, args.concat(more));};}// Compose (o'ngdan chapga)const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);// Pipe (chapdan o'ngga)const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
Mavzu bo‘yicha tushunchalaringizni interaktiv test orqali sinovdan o‘tkazing va natijalarni bilib oling.
Darslikda o‘rganilgan qoidalarga asosan real kod yozing, testlardan o‘tkazing va yechimlarni mustahkamlang.
Test Sinovi
Hali topshirilmagan (kamida 75% kerak)
Amaliy Masalalar
0 / 3 ta yechildi (kamida 75% kerak)
Dars sifati va mazmunini yaxshilash uchun o‘z haqqoniy bahoingizni qoldiring.
Mavzuni to‘liq o‘zlashtirish uchun test sinovi, amaliy kodlash va bog‘liq darslar
O‘z bilimingizni interaktiv test savollari orqali tekshiring va darhol xatolarni tahlil qiling.
Nazariyani real kod yozish bilan mustahkamlang, avtomatik testlardan o‘ting va XP to‘plang.
Kurs bo‘yicha keyingi va bog‘liq mavzular: