Photo by Stephanie Harvey on Unsplash

JS ILE FONKSIYONEL PROGRAMLAMA

Yazılımda Fonksiyonel Düşünmek -(Currying)

Örnek bir yazılımı fonksiyonel olarak geliştirerek. Mevcut programlama paradigmamızdan ne gibi farklar olduğunu analiz edelim. İlk olarak Curried Functions bahsedeceğim

Frontend Development With JS
3 min readFeb 6, 2020

--

Bu yazıyı daha önceden yazmış olduğum JS ile Fonksiyonel Programlama yazısının bir devamı olarak yazıyorum. Bir çok kavramı tek bir yazıda ele almanın yaratacağı karmaşıklıktan kaçmak için bu şekilde bir yönteme başvurdum.

İster nesne tabanlı programlama olsun, ister fonksiyonel programlama olsun, yazılım sürekli olarak temel elemanların birbirini kapsaması, kullanması ve birleşimi sonucu oluşur. Aşağıda da bu composition kavramının nasıl işletildiğini anlatmaya çalışacağım.

“Composition: the act of breaking a complex problem down into smaller problems, and composing simple solutions to form a complete solution to the complex problem.” (Eric Elliott)

1. Birbirlerini Kapsayan Fonksiyonların Çağrılması

2 tane fonksiyonumuz olsun. İlkinin çıktısını, diğerine verdiğimiz fonksiyon türlerini deneyelim ve her fonksiyon çalıştığında bunu console log olarak basalım. Örneğin f(g(x))

  • Birincisi gelen girdi değerini 1 ile toplayan
  • İkincisi gelen değeri 2 ile çarpan

Procedural Programlama

Procedural programlama benim alıştığım yöntem. En az ortak değişkeni kullanalarak burdaki ara çıktılar için result değişkeni kullandım.

function addOne(x){return x+1;}
function multiplyTwo(x){return x*2;}
function doStuff(x){
let result=addOne(x);
console.log(`after addOne ${result}`)
result=multiplyTwo(result);
console.log(`after multiplyTwo ${result}`)
}
doStuff(20);
//after addOne 21
//after multiplyTwo 42

Fonksiyonel Programlama

Fonksiyonel programlamada ise amacımız arka arka çağırma işlemini sizin yapmamızın yerine pipe fonksiyonu ile soyutluyoruz. pipe fonksiyonun çalışması için her seferinde 1 parametre alarak çalışan fonksiyonlara ihtiyacımız var. Trace fonksiyonumuzda 2 parametre alıyor bunu tek parametre alan hale nasıl getirebiliriz Currying mekanizması bunu sağlıyor.

const g = n => n + 1;
const f = n => n * 2;
const trace = label => value => {console.log(`${ label }: ${ value }`); return value;};
const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x);
const doStuffFunctional = pipe(
g,
trace('after g'),
f,
trace('after f'));
doStuffFunctional(20);

Curried Functions Nedir?

Curried fonksiyonlar birden fazla parametre alan fonksiyonlar yerine her seferinde bir parametre alacak şekilde fonksiyonun yapılandırılmasıdır. Bunuda 1 parametre alıp geriye diğer parametreyi alacak fonksiyonu dönerek gerçekleştirir.

function sum(a,b){return a+b};
function sumCurried(a){return function(b){return a+b}};
const sumES6=(a,b)=>a+b;
const sumCurriedES6=(a)=>(b)=>a+b;
console.log(sum(3,2));
console.log(sumCurried(3)(4));
console.log(sumES6(1,2));
console.log(sumCurriedES6(2)(4));

Timur Sevimli’den gelen yorum üzerine, aşağıdaki kısmı ekledim. Gönderdiği örnekte; Çok parametre alan fonksiyonları nasıl çoklu parametreden tekli parametreli birbiri ardına çağrılabilecek fonksiyona dönüştürdüğünü görebilirsiniz.

const curry = (fn, ...par) => {
const curried = (...args) => (
fn.length > args.length ?
curry(fn.bind(null, ...args)) :
fn(...args)
);
return par.length ? curried(...par) : curried;
};


const sum4 = (a, b, c, d) => (a + b + c + d);

const f = curry(sum4);
const y1 = sum4(1, 2, 3, 4);
const y2 = f(1, 2, 3, 4);
const y3 = f(1, 2, 3)(4);
const y4 = f(1, 2)(3)(4);
const y5 = f(1)(2)(3)(4);
const y6 = f(1)(2, 3, 4);
const y7 = f(1)(2)(3, 4);
const y8 = f(1, 2)(3, 4);
const y9 = curry(sum4, 1, 2, 3, 4);
console.log(y1, y2, y3, y4, y5, y6, y7, y8, y9);Ja

Yukarıdaki örneği denediğimde gerçektende f = curry(sum4) otomatik tek parametreyle veya farklı parametreler ile çağırabilecek hale getiriyor.

Benzer bir yaklaşım aşağıdaki curry2 fonksiyonu ile de yapılabiliyor. Benzer şekilde aldığı fonksiyonları tek tek argüman alabilir hale getiriyor.

function add(x, y, z) { return x + y + z;}

function curry2(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
};
}
};
}

const curriedAdd = curry2(add);

console.log(curriedAdd(1)(2)(3)); // Output: 6

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--