Funksional dasturlash

JavaScript Lisp yoki Haskell kabi sof funksional dasturlash tili emas, lekin JavaScript'ning funksiyalarni obyektlar sifatida boshqara olishi bizga JavaScript'da funksional dasturlash usullaridan foydalanish imkonini beradi. map() va reduce() kabi massiv metodlari funksional dasturlash uslubiga ayniqsa yorqin misol bo'la oladi. Keyingi bo'limlar JavaScript'da funksional dasturlash usullarini ifoda etadi. Ular yaxshi dasturlash uslubi uchun ko'rsatma sifatida emas, balki JavaScript funksiyalarining qudratini kengroq anglashga yordam beruvchi, tafakkurni kengaytiruvchi tadqiqot sifatida mo'ljallangan.

Massivlarni funksiyalar yordamida qayta ishlash

Tasavvur qiling, bizda sonlar massivi bor va biz bu qiymatlarning o'rta arifmetik qiymati va standart chetlanishini hisoblamoqchimiz. Buni funksional bo'lmagan uslubda quyidagicha amalga oshirishimiz mumkin:

Xuddi shu hisob-kitoblarni map() va reduce() massiv metodlaridan foydalanib, ixcham funksional uslubda ham amalga oshirishimiz mumkin (bu metodlarni eslab olish uchun §7.8.1-bo'limga qarang):

Kodning bu yangi versiyasi birinchisidan ancha farqli ko'rinadi, lekin u hali ham obyektlarda metodlarni chaqirmoqda, shuning uchun unda ba'zi obyektga yo'naltirilgan an'analar saqlanib qolgan. Keling, map() va reduce() metodlarining funksional versiyalarini yozamiz:

Bu map() va reduce() funksiyalari yaratilganidan so'ng, o'rta arifmetik qiymat va standart chetlanishni hisoblaydigan kodimiz endi quyidagicha ko'rinadi:

Yuqori tartibli funksiyalar

Yuqori tartibli funksiya (higher-order function) — bu funksiyalar ustida ishlaydigan, argument sifatida bir yoki bir nechta funksiyani qabul qilib, yangi funksiya qaytaradigan funksiyadir. Quyida misol keltirilgan:

Bu not() funksiyasi yuqori tartiblidir, chunki u argument sifatida funksiya qabul qiladi va yangi funksiya qaytaradi. Yana bir misol sifatida, quyidagi mapper() funksiyasini ko'rib chiqamiz. U argument sifatida funksiya qabul qiladi va o'sha funksiya yordamida bir massivni boshqasiga moslashtiradigan (map) yangi funksiya qaytaradi. Bu funksiya avvalroq yaratilgan map() funksiyasidan foydalanadi va bu ikki funksiyaning qanday farq qilishini tushunishingiz muhimdir:

Quyida yana bir, umumiyroq misol keltirilgan. U f va g degan ikkita funksiyani qabul qilib, f(g())'ni hisoblaydigan yangi funksiya qaytaradi:

Keyingi bo'limlarda keltirib o'tiladigan partial() va memoize() funksiyalari yana ikkita muhim yuqori tartibli funksiyalardir.

Funksiyalarni qisman qo'llash

Biror f funksiyasining bind() metodi (§8.7.5) f'ni belgilangan kontekstda va belgilangan argumentlar to'plami bilan chaqiradigan yangi funksiya qaytaradi. Biz buni funksiyani obyektga bog'laydi va argumentlarni qisman qo'llaydi deymiz. bind() metodi argumentlarni chap tomondan qisman qo'llaydi — ya'ni, siz bind()'ga uzatgan argumentlar asl funksiyaga uzatiladigan argumentlar ro'yxatining boshiga joylashtiriladi. Lekin argumentlarni o'ng tomondan ham qisman qo'llash mumkin:

Bu qisman qo'llash funksiyalari bizga allaqachon mavjud bo'lgan funksiyalardan yangi va qiziqarli funksiyalarni osongina yaratish imkonini beradi. Quyida bir nechta misollar keltirilgan:

Qisman qo'llashni boshqa yuqori tartibli funksiyalar bilan birlashtirganimizda, u yanada qiziqarliroq tus oladi. Mana, masalan, avvalroq ko'rsatilgan not() funksiyasini kompozitsiya va qisman qo'llash yordamida yaratishning bir yo'li:

Biz, shuningdek, kompozitsiya va qisman qo'llashdan foydalanib, o'rta arifmetik qiymat va standart chetlanish hisob-kitoblarimizni ekstremal funksional uslubda qayta bajarishimiz mumkin:

E'tibor bering, o'rta arifmetik qiymat va standart chetlanishni hisoblaydigan bu kod butunlay funksiya chaqiruvlaridan iborat; unda hech qanday operatorlar ishtirok etmayapti va qavslar soni shunchalik ko'payib ketdiki, bu JavaScript kodi Lisp kodiga o'xshab qoldi. Yana bir bor aytaman, bu men JavaScript dasturlashi uchun targ'ib qiladigan uslub emas, lekin JavaScript kodi qanchalik chuqur funksional bo'lishi mumkinligini ko'rish qiziqarli bir mashqdir.

Memoizatsiya

§8.4.1-bo'limda biz avval hisoblangan natijalarini keshlaydigan faktorial funksiyasini yaratgan edik. Funksional dasturlashda bu turdagi keshlash memoizatsiya (memoization) deb ataladi. Quyidagi kod argument sifatida funksiya qabul qilib, o'sha funksiyaning memoizatsiya qilingan versiyasini qaytaradigan yuqori tartibli memoize() funksiyasini ko'rsatadi:

memoize() funksiyasi kesh sifatida ishlatish uchun yangi obyekt yaratadi va bu obyektni lokal o'zgaruvchiga tayinlaydi. Shunday qilib, u qaytarilgan funksiya uchun xususiy bo'lib qoladi (closure'da). Qaytarilgan funksiya o'zining argumentlar massivini satrga o'zgartiradi va bu satrni kesh obyekti uchun xossa nomi sifatida ishlatadi. Agar keshda qiymat mavjud bo'lsa, u uni to'g'ridan-to'g'ri qaytaradi. Aks holda, u bu argumentlar uchun qiymatni hisoblash maqsadida ko'rsatilgan funksiyani chaqiradi, o'sha qiymatni keshlaydi va uni qaytaradi.

Quyida memoize()'dan qanday foydalanishimiz mumkinligi ko'rsatilgan: