4 Haziran 2020 Perşembe

Functional Programming

Giriş
Functional Programming (FP) yan etkisi olmayan programlama yöntemi. Bu yöntemde yazılım Predicate ve Function olarak nitelendirebileceğim programlama yapıları üzerine inşa edilir.Nesneye Yönelik Programlamada, veri ve metod bir arada, sınıfın içinde bulunmasına rağmen, FP'de metodlar veri tutmazlar.
Aşağıda konuyla ilgili aldığım notlar var.

FP Ne Zaman Kullanılır
FP Nesneye Yönelik Programlamanın (Object Oriented Programming) yerini alır mı almaz mı bilmiyorum, ancak matematiksel olarak modellenebilen yani bir formül olarak temsil edilebilen kodları geliştirmek için çok uygun bir yöntem.

FP ve OOP Arasındaki Düşünme Farkı Nedir
Tasarım anlamındaki farkın açıklaması şöyle. Object Oriented Programming History yazısına da bakabilirsiniz.
When explaining the difference between OOP and FP, I often resort to a (massively oversimplified) approach in how both of these approaches break down a complex problem into its constituent parts, but they use a different order of operations.

 A customer wants to purchase a product. They contact a vendor, ask for a pricing, buy the  product and then the vendor   ships the order.

An OOP developer breaks it down like this:

 A Customer wants to purchase a Product. They contact a Vendor, ask for a Pricing, buy the Productand then the Vendor ships   the Order.

In short, an OOP developer first defines "things that exist" (objects/entities/...), and will at a later stage write the behaviors (interactions between objects).

But an FP developer breaks it down like this:

 A customer wants to purchaseProduct. They contactVendor, askForPricing, buyProduct and then the vendor shipsOrder.

In short, a FP developer first defines "things that can be done" (features/functions/actions), and will at a later stage write the necessary data (objects/entities/...) that are needed to chain these actions together.

In both approaches, you will eventually have developed both the actions (purchasing, contacting, ...) and the data (customers, products, ...), but you first defined one before you defined the other. OOP developers start with the data, FP developers start with the actions.

Alan Bilgisi
İster Functional, ister Object Oriented programlama yapılıyor olsun, yazılımcının alan bilgisine sahip olmaya çalışması gerekir. Geliştirme yöntemi bu ihtiyacı hiç bir zaman ortadan kaldırmıyor. Açıklaması şöyle.
Software is a knowledge-intensive area. And a big part of the software engineer's work is to extract the domain knowledge from the users and domain expert, abstract it, and transform it it implementable data structures and algorithms.

Control Flow
Imperative dillerde kontrol aşağıdaki gibidir.
int sumList(List<int> list) {
  int sum = 0;
  for(int n = 0; n < list.size(); n++) {
    sum = sum + list.get(n);
  }

  return sum;
}
Functional diller ise aşağıdaki gibidir.
fun sumList([], sum) = sum
 |  sumList(v::lst, sum) = sumList(lst, v+sum)
Yani daha küçük metodların bir araya gelerek büyük bir işi yapmasına benzer. Örnekte her metod işini bitirdikten sonra yeni bir değer döner. Yeni değer bir sonra metoda girdi olarak kullanılır.
smallestEven = head . sort . filter even
Özel Function'lar
NOP Function
NOP metodun içi boştur.
function noop(){}
Identity Function
Identity Function verilen parametreyi döner.
function(a){return a}
Exception
Functional Programming ve Exception yazısına taşıdım.

Döngü
Functional Programming Pure Function yazısına taşıdım.

Sadece Function Kullanarak C ile Funtional Programming Olur mu?
Olmaz, çünkü şeklen sadece metodlara dayalı görünse de esasen First Class Function vs. gibi functional programming'in özü olan kullanım şekillerini dil desteklemez.

F#
F# functional bir dil olarak tasarlanmış. Ancak .Net kütüphanelerini kullandığı için yan etkiye sahip olabiliyor.

First Class Function Nedir?
First Class Function bir metodun değer olarak kabul edilmesi, değişkene atanabilmesi, saklanabilmesi anlamına gelir. Tipik Nesneye Dayalı (Object Oriented) yöntemlerde, metod nesneye ait kabul edildiği için First Class değildir. Dolayısıyla ikinci sınıftırlar. OO ile ayrımı göstermek için bu kavram geliştirilmiştir.

High Order Function Nedir?
Bir metodu girdi olarak alan ve gerekirse başka bir metod dönebilen metoda High-order function denilir. High Order Function, First Class Function kavramı ile yakından bağlantılıdır.


Yan Etkinin Olmaması Nedir ?
İngilizcesi Side Effect. Side Effect kat bir bakış açısıyla yazılımın herhangi bir şeyin durumunu değiştirmemesi olarak açıklanıyor. Örneğin diske bir şey yazılması, GUI'de bir düğmenin etkinleştirilmesi bile side effect olarak kabul edilir.

Ben bu tabirini çok daha basitleştirip bir fonksiyon kendisine parametre olarak geçilen değeri veya global bir değişkeni değiştirmemesi olarak kabul ediyorum. Global veri kullanılamadığı için functional diller recursive (öz yinelemeli) işlerde iyidirler. Yan etkisi olmayan bir metod şöyledir
int square(int x) { return x * x; }
Yan etkisi olan metod ise şöyledir. Aşağıdaki metodların hangi sırada çağırıldığı sonucu değiştirir.
int n = 0;
int next_n() { return n++; }
int set_n(int newN) { return n = newN; }

Referentially Transparent Nedir?
Referential Transparency yan etkisinin olmaması ile yakından ilgili. Yan etki olmadığı için işlem sırası önemsiz hale gelir.  Yani metod çağrısı gerekirse sonucu ile değiştirilebilir anlamına gelir.
En önemli faydası paralel programlamayı çok kolay hale getirmesidir.  Açıklaması şöyle.
The "normal" way of phrasing what a pure function is, is in terms of referential transparency. A function is pure if it is referentially transparent.

Referential Transparency, roughly, means that you can replace the call to the function with its return value or vice versa at any point in the program, without changing the meaning of the program.

Örnek
Şu kodlar pure değil
function a() { return Date.now(); }
function b() { return window.globalMutableVar; }
function c() { return document.getElementById("myInput").value; }
function d() { return Math.random(); }
Örnek
Örneğin şu kodda
a || b
her sub-expression paralel olarak çalıştırılabilir.

Örnek
Aşağıdaki Pyton örnekle Refrentially Transparent değildir!
counter = 0

def foo(x):
  global counter

  counter += 1
  return x + counter
Bu metodun iki kere çağırılması ile
foo(x) + foo(x)
değerinin ike ile çarpılarak çağırılması
2 * foo(x)
program üzerinde farklı etki yaratır.

Functional ve Object Oriented Programming'te Parametre Kullanımı
Her iki yöntem arasındaki ortak nokta, bir metoda parametre geçerken, parametre ve metod arasında bağımlılık yaratılması. Law of Demeter, Loose Coupling, Keep It Simple Stupid (KISS, You Aren't Gonna Need It (YAGNI) It gibi yöntemler, OO tabanlı olmalarına rağmen, functional programming için de kullanılabilirler.

Law Of Demeter için buraya bakabilirsiniz.

Loose Coupling arayüzler veya mesajlaşma altyapısı kulllanılmasını tavsiye ediyor.

KISS ise en kolayı ne ise onu yap diyor. YAGNI ise az kullanılan sınıfları ekleme diyor.

Functional Programming Neden Moda Oldu?
Benim gördüğüm şu anki en geçerli neden, FP ile paralel programlama yapmak çok daha kolay. Dolayısıyla FP işlemci kullanımını üst seviyelere getiren işler için uygun. Buradaki açıklamada Java 8 ile yeni gelecek olan Lambda yapısındaki şu cümle önemli.
"We have inverted the flow of control in the operation," Geotz said, comparing Lambda code with traditional code that uses an iterator. When using an iterator, the user controls how collections are processed and when parallel processing should occur. With Lambda, the user simply describes how a collection should be manipulated and the framework abstracts away the low-level processing details. "With Lambda, the client says to the library, 'here is the function.' And that's what enables the library to do the parallelism without the user having to write all of the fork-join junk. It uses fork-join under the hood, breaks it down and does a parallel decomposition."

FP ve Recursion
Recursive metodlar da paralel çalıştırılabilirler.

FP Kavramları
Kavramları buradan aldım.

1. Functional Composition
Basit fonksiyonları birleştirerek daha karmaşık bir fonksiyon oluşturmak. Unix'teki pipe kullanımına benziyor. Bir uygulamanın çıktısı, bir başka uygulamanın girdisi olarak kullanılıyor.

2. Combinatory Logic
Açıklama yaz

3. Map
Map/Reduce algoritmasının map bölümü. Algoritma şu adımlardan oluşur.
Map -> Shuffle -> Sort -> Reduce
Her Reducer'ın, Sort adımı sonrasında bir key değerine ait tüm value nesnelerini alması garanti edilir.

4. Filter
Açıklama yaz

5. Reduce
Map/Reduce algoritmasının reduce bölümü


Java 8
Konuyu Java 8 Stream Sınıfları yazısına taşıdım.

Guava - Java 8 varken Kullanmayın
Guava FP yapabilmeyi mümkün kılan
- Predicate ve
- Function arayüzlerini sunuyor.

Bu konuyu ilk ele almama sebep olan yazı burada. Guava ile Fonksiyonel Programlama yapmayı anlatan sayfa burada. Guava Fonksiyonel Programlama kabiliyetini Java 7 ve daha düşük sürümlerde kullanmak için gayet güzel. Bence Java, C#'a nazaran bu konuda henüz çok geride.


Apache Commons - Java 8 varken Kullanmayın
Guava'ya benzer bir şekilde Predicate sınıfı sunuyor.

2 yorum:

  1. Mehmet temel6 Mart 2019 22:09

    Reactive programlamayla farki nedir bunun?

    YanıtlaSil
    Yanıtlar
    1. Functional Programming, Object Oriented Programlama yerine kullanılabilen bir başka seçenek. Reactive programlama verinin nasıl aktığı ile ilgili. Amacı eşzamanlılığı(concurrency) artırmak.

      Sil