functional programming etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
functional programming etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

8 Ocak 2021 Cuma

Functional Programming Monad

Giriş
Açıklaması şöyle
Monads are heavily used in most functional programming languages. In Haskell, for example, they are essential and appear everywhere, in all kinds of applications and libraries.                            

On the other hand, monads are rarely used in popular, non-pure-functional programming languages like C#, Java, Python, etc.
Anladığım kadarıyla Monad kullanarak Function Composition yapabiliyoruz. Yani Java ile düşünürsek nested function call gibi düşünülebilir. Bu çağrı zincirinde önce string'in başında/sonunda bulunan boşluklar temizlenir, büyük harfe çevrilir ve başına ünlem işareti konulur.
return appendExclam ( toUpperCase ( trim ( sentence ) ) );
Ancak bu kullanımda bir eksiklik var. Eğer hata bulunursa bunu yukarıdaki metoda geçme yolu yok. Monad bunu da hallediyor.

Kotlin Either Monad
Açıklaması şöyle
- Either type represents values with two possibilities, either Left or Right
- Convention dictates that Left is used for Failure and Right is used for Success.
- Mnemonic: Right also means correct.
İskeleti şöyle
sealed class Either<out A, out B> {
    data class Left<A>(val value: A) : Either<A, Nothing>()
    data class Right<B>(val value: B) : Either<Nothing, B>()
}
Örnek
Şöyle yaparız
data class Account private constructor(val balance: BigDecimal) {

  companion object {
    fun create(initialBalance: BigDecimal): Either<NegativeAmount, Account> =
      if (initialBalance < 0) Either.Left(NegativeAmount)
      else Either.Right(Account(initialBalance))
  }
}




3 Aralık 2020 Perşembe

Functional Programming ve Exception

Giriş
Yazıya girmeden önce şunu belirtmek lazım. Java gibi dillerde checked exception fırlatan metodlar Functional Programming ile rahatça kullanılamadığı için, bazı makalelerde exception'ları emen/gizleyen uncheckedXXX şeklinde metodların/sınıfların kullanılması öneriliyor. Bir örnek burada.
Ben bu yönteme kesinlikle karşıyım, hatta çok tehlikeli

Imperative programlama dillerinde exception hatalı durumlarda Control Flow'u değiştirmek için kullanılır. Functional programlama dillerinde ise genelde exception yoktur.

Örnek
Klasik Java'da şöyle yaparız. Burada C++, Java, C# gibi dillerdeki try/catch/finally yapısı var.
FileReadService service = new FileReadService();
try {
  String content = service.readFile("no-such-file.txt");
  return content;
} catch (BadFilenameException ex){
  System.out.println("No file found");
  return readFromCache();
}
Functional Diller Exception'lardan Nasıl Kurtuldular?
Açıklaması şöyle. Yani hatalı durumlarda bile hatayı temsil eden bir "şey" dönuyorlar.
How does a Function Programming, such as Elm, achieve "No runtime exceptions"?

That's easy. You simply don't write functions that fail.

That might sound simplistic, but that's the gist of it.
Functional Kullanım

Örnek - Sonuç Döndürmeyen Metod
Burada hayali bir dil var. someOperation() metodu bir lambda. Başarı ve hata durumları için kod yazılıyor
service.someOperation(result -> {
  if (result.succeded()){
    // do something
  } else {
    // failure
  }
});
Örnek - Sonuç Döndüren Metod
Burada hayali bir dil var ve metod çağrısı özel bir nesne döndürülüyor. Bu nesnenin hata taşıması durumunda getOrElse() metodunu çalışıyor.
FileReadService service = new FileReadService();
String content = service.readFileSafely("no-such-file.txt").getOrElse(readFromCache());

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.

11 Kasım 2019 Pazartesi

Functional Programming Pure Function - Yan Etkisi Yoktur ve Aynı Girdi İçin Aynı Sonucu Verir

Giriş
Açıklaması şöyle. Yani yan Etkisi Yoktur ve Aynı Girdi İçin Aynı Sonucu Verir
Most sources define a pure function as having the following two properties:
- Its return value is the same for the same arguments.
- Its evaluation has no side effects.
Önemli Not
Object Oriented programlamaya alışkın olanların itirazı şöyle
“This is puristic nonsense!” you say. “Intellectual masturbation! Software should be modeled after real-world, mutable objects!”
Functional programlamaya alışkın olanların itirazı da şöyle. Çünkü OO şeklinde yazılan bazı kodlar gerçekten çok büyük ve anlaması zor olabiliyor.
You shouldn't need several hours to understand what a method, class, or package does. If you need a lot of mental effort to even start programming, you will run out of energy before you can produce quality. Reduce the cognitive load of your code and you will reduce its amount of bugs.
Aslında Functional veya Object Oriented programlamadan sadece birisini tercih etmek zorunda değiliz. Bu ikisi kolayca bir arada kullanılabiliyor.

Functinal Programming bize öncelikle kodu işlevsel daha küçük parçalara bölme imkanı veriyor. Buna "Partitioning by Functionality" veya "Breaking It Up Into Composable Units" diyebiliriz. Bu bölümleme esnasında yukarıdaki 2 kurala da uyunca anlaması, okuması ve test etmesi daha kolay kodlar ortaya çıkıyor

Pure Function Örnekleri
Örnek

Şöyle yaparız.
const add = (x, y) => x + y;

add(2, 4); // 6
Impure Function Örnekleri
Örnek
Şu kod impure çünkü harici state'ı değiştiriyor.
let x = 2;

const add = (y) => {
  return x += y;
};

add(4); // x === 6 (the first time)
add(4); // x === 10 (the second time)
Örnek
Şu kod impure çünkü harici state'i okuyor veya tutuyor.
const exchangeRate =  fetchFromDatabase(); // evaluates to say 0.9 for today;

const dollarToEuro = (x) => {
  return x * exchangeRate;
};

dollarToEuro(100) //90 today

dollarToEuro(100) //something else tomorrow
Bu kodu değiştirmek için şöyle yaparız.
const exchangeRate =  fetchFromDatabase(); // evaluates to say 0.9 for today;

const dollarToEuro = (x, exchangeRate) => {
  return x * exchangeRate;
};
2. Döngü
Functional dillerderde aşağıdaki gibi döngüler impure olarak kabul edilirler.
int as_int(char *str)
{
  int acc; /* accumulate the partial result */

  for (acc = 0; isdigit(*str); str++) {
    acc = acc * 10 + (*str - '0');
  }

  return acc;
}
Döngüler diğer metodlar kullanılarak yapılır.
int as_int(char *str)
{
  return fold(takeWhile(isdigit, str), 0, int function(char *chr, int acc) {
      return acc * 10 + (chr - '0');
    });
}