Scala Higher Order ve Anonymous Fonksiyonlar, Currying

2016, Jun 02    

Higer-Order Functions:

Scala Higer-Order Fonksiyon tanımlamaya izin veir. Fonksiyonları diğer fonksiyonlara parametre olarak gönderebiliriz ya da işlemin sonunda elde ettiğimiz sonuç bir fonksiondur.

Örneğin; iki tam sayı arasındaki sayıların kübünü bulmak istiyoruz.

Burada sumCubes’ün içerisinde cube fonksiyonunu çağırmak yerine fonksiyonu direk parametre olarak gönderebiliriz. İfadeyi şu şekilde tanımlarsak;

Bu tanımladığımız ifadeyi küp ve faktoriyel bulma ile örneklendirebiliriz.

Burada cube ve fact;

ifadeleri ile eşleşir.

Fonksiyon Tipi: a => b ifadesi bize “a” giriş değerini “b” ise sonuç değerini belirtir.

Bu ifadelerde dikkatinizi birşey çekmiş olmalı. Neden birden çok yardımcı fonksiyon tanımladık. Bu tanımlamaları yapmadanda işlemimizi gerçekleştirebilir miyiz? İşte bu kısımda devreye Anonymous Fonksiyonlar giriyor.

Anonymous Functions:

Fonksiyonları bir diğer fonksiyona gönderirken, parametre olarak geçen birçok küçük fonksiyonun oluşmasına sebep olur. Bu fonksiyonları def kullanarak tanımlamak bazen program yazan kişiye angarya yük olabilir.
Örneğin ekrana “abc” ifadesini yazmak istiyoruz. Bunu iki şekilde yapabiliriz. Birincisi def kullanarak;

def str = abc;
println(str)

İkinci yol ise direk ifadeyi yazarak.

println(abc)

Bu örnekde karakter dizileri değişmez literallerdir. Benzer olarak fonksiyonlarda literaller gibidir isimsiz fonksiyon yazmamıza izin verir. Bu fonksiyonlara Anonymous Functions adı verilir.

Anonymous Functions Syntax:

(x: Int) => x*x*x

Burada (x: Int) ifademizin parametresini , xxx ise esas kısmını oluşturuyor.

Yukarıdaki küp örneğini anonymous fonksiyon şeklinde tekrardan düzenlersek.

Peki biz bu ifadeyi daha sade bir hale getirebilirmiyiz. Tabiki evet.

Currying:

Amaci bir fonksiyona luzum dahilinde ihtiyaci oldugundan daha az parametre gonderebilmektir.

Çoklu Parametre Listesinin Açılımı:

Kullandığımız fonksiyonlar birden çok parametre içeriyorsa bunu currying mantığı kullanarak daha sade hale getirebiliriz.

def f(args1)....(argsn) = E 

Genel olarak fonksiyonara argüman gönderme işlemi bu şekilde yapılır. Eğer n değeri 1 den büyük ise yeni bir fonksiyon tanımlamalıyız;

def f(args1)...(argsn-1) = {def g(argsn) = E;g}

Daha sade bir şekilde ifadeyi Anonymous Function şekline getirisek;

def f(args1)....(argsn-1) = (argsn) => E

İşlemimiz n kez devam ediyor ise;

def(args1)...(argsn-1)(agsn) = E

Bütün parametreleri nested ve anonymous fonksiyon şeklinde yazarız.

def f = (args1 => (args2 => ...(argsn => E)...))

Bu tanımlama şekli Currying olarak isimlendirilir.

Hemen ufak bir örnek yapalım. Bir fonksiyon tanımlayalım. Bu fonksiyon a ve b arasındaki sayıların karelerini çarpsın.

Şimdide fact adlı bir fonksiyon tanımlayalım. Bu fonksiyon sayının faktöriyelini alsın ancak product fonksiyonunu kullanarak bunu gerçekleştirsin.