JavaScript’de Currying nedir?

Gökhan İpek
3 min readJan 17, 2021

--

Yıllar önce JavaScript’i yeni öğrenen alaylı bir yazılımcı iken (hala alaylıyım), o zamanlar, akıl hocam olarak gördüğüm bir arkadaşım, bana JavaScript’i daha iyi anlamak için Closure, Currying gibi kavramları öğrenmemi söylerdi. Bu kavramlar hep aklımdaydı, zaman içinde farkına bile varmadan kullanmaya başladım. Ancak özel olarak üzerine hiç eğilmemiştim. Şu anda çalıştığım şirket ile görüşürken, görüşme yaptığım arkadaşım şöyle bir soru sordu:

console.log(sum(2,3)) // 5console.log(sum(2)(3)) //5Bu iki durumu sağlayan bir method yazabilir misin?

Ve içimden şöyle dedim:

“Ah, çok kolay! Currying! bunu her zaman kullanıyorum zaten.”

Ve çözmeye başladım. Ancak belki de görüşmenin heyecanı ile çözemedim. Benim için tam bir hayal kırıklığıydı. Bu makalenin konusu da bu, umarım daha iyi kavramanıza yardımcı olur.

Higher-Order fonksiyonlar(HOF) ve Saf Fonksiyonlar(Pure Functions) gibi, Currying de programlama dillerinde bir konsepttir. Fonksiyonel programlama dillerinin bize sağladığı güzel bir avantaj olduğunu söyleyebiliriz. Yalnızca JavaScript değil Haskell, Scala, Clojure gibi farklı programlama dillerinde de kullanılır.

Currying kullanarak, fonksiyon dönen bir fonksiyon (bkz: Higher-order functions) yazabilirsiniz. Bunun bize faydası aşağıdaki gibi fonksiyonları,

function sum(a,b,c) {
return a + b + c;
};
sum(10,20,30);

buna çevirmemiz konusunda bize yardımcı olmasıdır.

const sum = (a) => {
return (b) => {
return (c) => {
return a + b + c
}
}
}
sum(10)(20)(30);

Yani en yalın şekilde, tüm argümanlar kullanılana kadar bize bir fonksiyon dönecek. Eğer Closure konsepti hakkında bilgi sahibiyseniz ya da duyduysanız, Currying’in Closure’lara bağlı olarak çalıştığını farkedeceksiniz.

Haklı olarak şu soru sorulabilir:

İstediğim sayıda argüman alacak bir fonksiyon yazabilecekken neden Currying kullanayım ki?

Bu durumda cevap olarak şunu verebilirim,

Eğer yazdığın fonksiyon 2–3'ten fazla argüman alıyorsa büyük ihtimalle bir şeyleri fazla karmaşık düşünüyorsun demektir.

Şaka bir yana, Currying ile ilgili öğrenmeye başladığımda aklıma gelen ilk soru buydu. Karmaşık düşünmekten bahsederken, Currying konseptinin de başlı başına karmaşık olduğu bir gerçek. Görünüm olarak en azından.

Kopseptin arkasında ise yalnızca matematik var.

Currying bize aslında birden çok argüman alan ve bunları frameworklerde kullanan fonksiyonlarla çalışmanın yolunu sağlar. Ayrıca matematikte bazı analitik teknikler yalnızca tek bir argümana sahip işlevlere uygulanabilir.

Bu son cümleyi lise ve üniversitede matematik dersinde duymuş olmanız kuvvetle muhtemel.

Sanırım bu yüzden yazılımcı olmak için matematik bilgisi önemli diyorlar

Peki bu bilgi gerçek hayatta(iş hayatında) nerede işimize yarayacak?

En basitinden, çalıştığınız projede aynı argümanı kullanarak iş yapan birden fazla method olduğunu düşünelim. Defalarca aynı argümanı çağırıp farklı şeyler dönüyorsunuz (return ediyorsunuz).

orderDeliveryDate metodunu bypass edersek,daha kısa şekilde aşağıdaki gibi olacaktır.

Yukarıdaki işlemi Currying olmadan şu şekilde yapardık:

Burada yalnızca 3 defa fazladan müşteri ismini yazdığımıza dikkat çekmek istiyorum. Bu durumu Hepsiburada, Trendyol gibi platformlarda milyonlarca sipariş için yapıyor olsaydık, Currying’in değeri daha iyi anlaşılıyor olacaktı.

Son olarak, daha önce React ve Redux kullandıysanız, aşağıdaki kullanımdan da haberdar olmanız muhtemel.

export default connect(mapStateToProps, mapDispatchToProps)(SomeComponent);

aslında kaynak kodlara göz gezdirdiğimizde bu satır ile yaptığımız şeyin de yukarda anlatılan kısmın aynısı olduğunu farkediyoruz. Daha fazla ayrıntı için kaynak kodunu inceleyebilirsiniz.

Aslında ortalama bir React kullanıcısı günlük hayatında farkında olmadan dahi Currying kullanıyor. Bu sebeble yazdığımız kodu daha iyi analiz etmek ve anlamak için Currying, closure gibi kavramlar ile ilgili daha fazla bilgi sahibi olmak yararlı diye düşünüyorum.

Okuduğunuz için teşekkür ederim. Sevgi ile kalın.

Kaynaklar ve daha fazla okuma için:
benestudio, codeburst, dev.to1, nypl, dev.to2

--

--