JS ILE FONKSIYONEL PROGRAMLAMA
Transducers
Yazılımda bir girdiyi dönüştürerek istenen farklı bir çıktılar oluşturan fiziksel parçalara Transducers (Transdüser) denir. Elektrik devrelerinde sinyal işleme, veya Yazılımda Data Flow (Veri Akışlarındaki) dönüştürme işlemlerinin soyutlanmasıdır.
--
Transducers daha iyi anlaşılması için aşağıdaki alıntıyla başlamak istiyorum. Transdüser aslında bizim hayatta sıklıkla kullandığımız fiziksel cihazlar.
Mikrofonlarda sesi algılamak için ses sensörleri, araçlarda egzoz gazlarını algılamak için oksijen sensörleri, ortam sıcaklığını algılamak için sıcaklık sensörleri, fabrikalarda gaz veya sıvı basıncını algılamak için basınç sensörleri veya otomatik kapılarda hareketle değişen ışık miktarını algılamak için kullanılan fotoelektrik sensörler (MühendisBeyinler.net)
Yazılım anlamında aslında genişleyebilir (composable), HoR(High Order Reducer) başka Reducer içerine alıp , geriye Reducer dönen yapılardır.
Not : High Order konusunu bilmiyorsanız. Bu konuda daha önceden yazmış olduğum
- High Order Functions Blog yazısını okumanızı öneririm.
- Code Sharing (High Order Components) blog yazısını okumanızı öneririm.
Bizim yukarıda bahsettiğimiz ise biraz daha özelleşmiş bir şey → High Order Reducer, yani High Order Function bir alt kümesi olarak düşünebiliriz.
Peki Reducer dediğimiz şey nedir ? Birden fazla değer alıp bunu birleştirip tek bir sonuç olarak dönen yapılardır.
// Sums: (1, 2) = 3
const add = (a, b) => a + b;
// Products: (2, 4) = 8
const multiply = (a, b) => a * b;
// String concatenation: ('abc', '123') = 'abc123'
const concatString = (a, b) => a + b;
// Array concatenation: ([1,2], [3,4]) = [1, 2, 3, 4]
const concatArray = (a, b) => [...a, ...b];
High Order Reducer yani Transducers denilen şeyler enumerable veri kaynakları üzerinde → arrays, trees, streams, graphs, vb üzerinde Reducer genişleyebilir şekilde devam ettirebilir yapılardır.
T(Reducer) → Reducer.
G(Reducer) -> T(Reducer) -> Reducer
Gerçek uygulamalardan bir örnek verdiğimizde durum daha iyi anlaşılacaktır. Aşağıdaki örnekteki filter, map fonksiyonları Transducerslar dır.
const cities=[
{name: 'Ankara', value: 2}
{name: 'Izmir', value: 1}
{name: 'Istanbul', value: 4}
]
const filterFn = ({value})= value>1;
const viewFn = ({name}) => name;
const result=cities.filter(filterFn).map(viewFn);
console.log(result); //[Ankara, Istanbul];
Bir önceki konuda Lens anlattığım gibi bizim aldığımız girdi bir stream, array vb
- filterelememiz
[10] → (filter) → [5]
- array içerisindeki objenin yapısını azaltmamız dışarıya çıkarmamız gerekebilir.
[ {name: ‘Ankara’, value: 2}, {name: ‘Istanbul’, value: 4}] → [ ‘Ankara,Istanbul]
- veya bu objenin içerisindeki değeri daha fazla arttırmamız gerekebilir
[ {name: 'Ankara', value: 2}, {name: 'Istanbul', value: 4}] →
[ {name: 'Ankara', value: 2, ab:'Ankara2'},
{name: 'Istanbul', value: 4, ab:'Istanbul4'}]
Tüm bu çabalar enumarable veri yapısında çalışmaya döngüleri, filtereleri, dönüştürmeleri olabildiğince soyutlamaktır.
Bu soyutlama işlemini yapan .filter()
, .map()
, .reduce()
, .concat()
fonksiyonlar Transducers diyoruz.
Ramda daki EricElliottJS blog yazısında yer alan örneği inceleyelim. Aşağıdaki örnek Ramda kütüphanesini kullanıyor.
import {
compose,
filter,
map,
into
} from 'ramda';
const isEven = n => n % 2 === 0;
const double = n => n * 2;
const doubleEvens = compose(
filter(isEven),
map(double)
);
const arr = [1, 2, 3, 4, 5, 6];// into = (structure, transducer, data) => result
// into transduces the data using the supplied
// transducer into the structure passed as the
// first argument.
const result = into([], doubleEvens, arr);console.log(result); // [4, 8, 12]
However, it does offer a different style of coding, a style that’s taken for granted in purely functional programming languages: Ramda makes it simple for you to build complex logic through functional composition. Note that any library with a
compose
function will allow you do functional composition; the real point here is: "makes it simple". (Scott Sauyet)
Yukarıda gördüğünüz gibi herşeyin olabileceğince fonksiyon olduğunu görebilirsiniz. Fonksiyonel programlama’da veriler üzerinde işleyen ve immutable çıktı üreten fonksiyonlar bulunur.
- isEven : Kendisine verilen değer çift minin cevabını veriyor (True/False)
- double: Kendisine verilen değeri 2 ile çarpıyor n * 2 => 2n
- filter(isEven): Enumarable bir veri yapısındaki değerlerin çiftin katları olacak şekilde filtrelemesi
- map(double) : Enumarable bir veri yapısında değerleri 2 ile çarpar ve aynı enumarable yapıyı döner.
- doubleEvens : [array] → filter(isEven) → map(double) → [array]
Burada Transducer arka arkaya çağrılarak bir veri flow oluşturulduğunu görebilirsiniz. Bunu müzik sinyali, video stream, veri akışı üzerinde uygulayabilirsiniz. ,
[ Source ] -> [ Mic ] -> [ Filter ] -> [ Mixer ] -> [ Recording ]
[ Enumerator ]->[ Transducer ]->[ Transducer ]->[ Accumulator ]
Referanslar
Okumaya Devam Et 😃
Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.