Photo by Scott Webb on Unsplash

JS ILE FONKSIYONEL PROGRAMLAMA

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

Onur Dayıbaşı
3 min readFeb 9, 2020

--

Örnek bir yazılımı fonksiyonel olarak geliştirerek. Mevcut programlama paradigmamızdan ne gibi farklar olduğunu analiz edelim. Bu yazıda Partial Applications’dan bahsedeceğim.

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.

Bir önceki yazımda Function Accepting Functions yazısında nasıl aynı parametredeki işlemleri fonksiyonlarıda parametre olarak geçirip işletebileceğimizi anlatmıştım. Ama fonksiyonumuz 2 parametre almak yerine 3 parametre, 4 parametre alan fonksiyon olduğunda sistemimizi nasıl genişleteceğiz. addTwo fonksiyonunu aşağıdaki sum2, sum3, sum4 destekleyecek hale nasıl getiririz.

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

Bunu ES6 ile array argümanı alacak şekilde geliştirebiliriz.

const sumReducer = (acc, val) => acc + val;
const sum=args=>args.reduce(sumReducer);
console.log(sum([1,2])); //3
console.log(sum([1,2,3])); //6
console.log(sum([1,2,3,4])); //10

Daha önceden Spread Kavramı olayı içerisinde apply, call, bind bir fonksiyonun parametrik olarak nasıl çalıştırabildiğimizden bahsettim. Öncelikle sum fonksiyonunu birden fazla sayıyı toplayabilen bir hale getiriyoruz. Partial Applications belli miktardaki argümanın bir kısmını önceden sabit alan ve geriye döndüğü fonksiyon ile daha az argüman alarak işlemleri tamamlamanız sağlayan fonksiyonlardır.

Aşağıdaki fonksiyonda 1 ile toplama işlemi sabit kısımdır. Bir ile toplamayı kalıp haline getirip içerisinde geçen parametreleri topladıktan sonra 1 rakamına bunu ekliyoruz

const sumReducer = (acc, value) => acc + value;
const sum=(...args)=>args.reduce(sumReducer);
console.log(sum(1,2)); //3
console.log(sum(1,2,3)); //6
console.log(sum(1,2,3,4)); //10
const partial=(fn,...args)=>(...arg2)=>fn.apply(null,[...args,...arg2]);
const addOne=partial(sum, 1);
console.log(addOne(4)); //5
console.log(addOne(10,2,3)); //16

Bu işlemi ilerletmek ve sum yanına multi koymak istersek. tek yapmamız gereken multi mantıklarını eklemek. Burda 2 ile çarpmak sabit.

const sumReducer = (acc, value) => acc + value;
const multiReducer = (acc, value) => acc * value;
const sum=(…args)=>args.reduce(sumReducer);
const multi=(…args)=>args.reduce(multiReducer);
const partial=(fn,…args)=>(…arg2)=>fn.apply(null,[…args,…arg2]);
const addOne=partial(sum, 1);
const multiTwo=partial(multi, 2);
console.log(addOne(10,2,3)); //16
console.log(multiTwo(3,5)); //30

partial vs partialRight arasında ne gibi farklar vardır. Verilen argümanların fonksiyonun sağında mı yoksa soldan → sağa sıra ile mi kullanılacağı arasındaki farktır. Aşağıdaki örnekte bir cümle kalıbı oluşturan bir fill fonksiyonu var. a, b parametreleri sırasının değişmesi cümleye farklı anlamlar veriyor. Toplama işlemindeki durumdan farklı. Partial işlemi ilk parametreyi kalemi veren haline getirirken partialRight kalemi alan kişi haline getiriyor.

const fill=(a, b)=>`${a} gives ${b} a pencil.`;
const partial=(fn,...args)=>(...arg2)=>fn.apply(null,[...args,...arg2]);
const partialRight=(fn,...args)=>(...arg2)=>fn.apply(null,[...arg2,...args]);
const aliGives=partial(fill,'Ali');
console.log(aliGives('Veli')); //Ali gives Veli a pencil.
console.log(aliGives('Ahmet')); //Ali gives Ahmet a pencil.
const aliReceives=partialRight(fill,'Ali');
console.log(aliReceives('Veli')); //Veli gives Ali a pencil.
console.log(aliReceives('Ahmet'));//Ahmet gives Ali a pencil.

Partial placeholder ( __ ) tanımlayıp uygulamanın istediğiniz kısmını sabit , istediğiniz kısmını dinamik hale getirebilirsiniz. Aşağıdaki örnekte kırmızı, yeşil ve mavi renk tonlarını oluşturabilirsiniz.

const hex=(r, g, b)=>'#' + r + g + b;
console.log(hex('11', '22', '33')) // "#112233"
const partialAny = (function() {
function partialAny(fn ,...orig) {
return (...partial) => {
const args = [];
for (let i = 0; i < orig.length; i++) {
args[i] = orig[i] === partialAny._ ? partial.shift() : orig[i];
}
return fn.apply(this, args.concat(partial));
};
}
partialAny._ = {};
return partialAny;
}());
const __ = partialAny._;const maxRed=partialAny(hex,"ff",__,__); //ffaabb
console.log(maxRed('aa','bb'));
const greenMax=partialAny(hex,__,'ff',__);//aaffbb
console.log(greenMax('aa','bb'));
const blueMax=partialAny(hex,__,__,"ff");//aabbff
console.log(greenMax('aa','bb'));

Referanslar

Okumaya Devam Et 😃

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

--

--