Algoritmaya Giriş #7 - Fonksiyonlar

 Evet, Algoritmaya Giriş serimizde şimdiye kadar algoritmanın ne olduğu, girdi ve çıktı işlemlerinin nasıl yapıldığı, değişkenlerin nasıl tanımlanıp kullanıldığı ve koşul ile döngü yapılarının tanımı ve kullanımına işledik. Buraya kadar olan kısım, algoritma yapmayı öğrenmenin "emekleme zamanı" denilebilecek kısmını oluşturuyor. Ancak artık bu yazı ile birlikte emeklemeyi bırakıp yürümeyi öğreniyoruz. Çünkü programlamanın son derece önemli bir yapıtaşı olan fonksiyonlara geçiyoruz.

Fonksiyonların programlama dünyasındaki önemi kesinlikle yadsınamaz bir düzeydedir. Temel amaç tekrarlı kod bloklarını tekrar tekrar yazmayı önlemek olsa da, sağladığı faydalar bunlardan fazladır. Fonksiyonlar tıpkı değişkenler gibi isimlendirilebildiklerinden dolayı hangi alanda hangi algoritmanın çalışacağını belirlemeniz kolaylaşır. Yaptığınız yazılımın her bir davranışını belli parçalara ayırırsınız. Bunları sağlamanıza izin verdiğinden dolayı fonksiyonlar son derece önemli ve kullanışlı yapılar olarak programlama dünyasında yerini almıştır.

Bu seride bugüne kadar yaptığımız her bir örnek aslında birer fonksiyon olarak yazılabilir. Örneğin sadece ekrana "Hello, World!" yazmaya yarayan bir helloWorld fonksiyonu tanımlayabilirsiniz. Veya bir yapay zeka uygulaması geliştiriyorsanız bu uygulamanın eğitimini ve testini gerçekleştiren iki ayrı fonksiyon tanımlayabilirsiniz. Fonksiyonlarla yapabileceklerinizin sınırı yok denecek kadar azdır, olan yerde de zaten devreye obje odaklı programlama giriyor.

İsterseniz bu kadar açıklamadan sonra hiç vakit kaybetmeden fonksiyonlara giriş yapabiliriz.

Fonksiyon Tanımlama


Fonksiyonlara "Hello, World!" demek için aşağıdaki basit programcığı ele alalım.


Bu programcığımız, yukarıda bahsettiğim sadece "Hello, World!" yazmaya yarayan programcığımız. Biz bu örnek için bu işlemi bir fonksiyona yaptıracağız. Tabii ki bunun için programımıza bir fonksiyon eklememiz gerekiyor. Bunun için ise Flowgorithm'deki "Fonksiyon Yöneticisi" aracından faydalanacağız.

Fonksiyon yöneticisi aracımız, Flowgorithm'in uygulama menüsünde şu an seçili olan simge, iki pembe/mor elipsli olan. Fonksiyon yöneticisi aracılığıyla biz Flowgorithm'de uygulamamıza fonksiyon ekleme, bu fonksiyonları değiştirip silme işlemlerini yapabiliyoruz. Bu simgeye tıkladığımızda karşımıza şu menüler çıkıyor:


Burada soldaki menü bizim Fonksiyon yöneticisi menümüz. Burada fonksiyon ekleme, düzenleme, silme gibi işlemleri gerçekleştirebiliyoruz. Bu menüdeki "Ekle" butonuna tıkladığımızda ise sağdaki menü çıkıyor. Burada fonksiyonumuzun ismini, alacağı parametreleri ve bu fonksiyonun ne tür bir değer döneceğini belirtiyoruz. Bu örneğimizde sadece "Hello, World!" yazdıran bir fonksiyon yazacağımız için dönüş tipimizi "Yok" veya "Void" olarak belirliyoruz.


Yeni fonksiyonumuzu tanımladığımızda karşımıza "helloWorld" ve "Son" blokları çıkıyor. Programımız, tıpkı ilk boş programımız gibi bize boş, yani hiç bir şey yapmayan bir fonksiyon oluşturuyor. Programımızdaki fonksiyonlara "Fonksiyon Yöneticisi" simgesinin yanındaki aşağı ok işaretinden erişebiliyoruz. Burada programımızdaki fonksiyonlar olan "Ana" ve "helloWorld" fonksiyonları görülüyor.

Buradaki "Ana" sekmesine tıklayıp ana programımıza dönüyoruz ve Output/Çıktı bloğumuza sağ tıklayıp o bloğu siliyoruz (fonksiyonlar arasında kesme/yapıştırma işlemi Flowgorithm'de desteklenmiyor, en azından kullandığım sürümde). helloWorld fonksiyonumuza da "Hello, World!" yazdıran bir Output bloğu ekliyoruz.

Peki biz bu yazdığımız fonksiyonu nasıl çalıştıracağız?

Fonksiyon Çağırma


Flowgorithm'de fonksiyon çalıştırmak için ana programa geri dönüp "Main" ve "End" (veya Türkçe kullanıyorsanız "Ana" ve "Son") blokları arasındaki oka tıklayıp bir "Call" fonksiyonu ekliyoruz.


Burada "?if?" bloğu altında bulunan "Call" bloğunu programımıza ekledikten sonra çift tıklayarak çıkan ekranda fonksiyonumuzun ismini, yani helloWorld'u kutucuğa yazıyoruz. OK deyip programımızı çalıştırıyoruz. Programımız ve çıktımız şu şekil olmalı.

Ana program



helloWorld fonksiyonumuz


Programımızın helloWorld fonksiyonunu çağırdığının kanıtı


Flowgorithm program menüsündeki Step (>|) tuşuna bastığınız zaman program Main'den başlayacak ve helloWorld'e gidecek, akabinde helloWorld başlangıç bloğundan Output bloğuna geçerek ekrana "Hello, World!" metnini yazdırıp fonksiyondan çıkacak, akabinde başka hiçbir komut olmadığı için program sonlanacaktır.

Değer Döndüren Fonksiyonlar


Yukarıda yazdığım basit fonksiyon, ana programa kullanabileceği herhangi bir değer döndürmedi, sadece ekrana "Hello, World!" yazıp çıktı. Ana programa değer döndürmeyen fonksiyonlar "void" fonksiyonlar olarak biliniyor ve ekrana hata mesajı yazdırmak, bazı program ayarlarını değiştirmek gibi amaçlarla kullanılıyorlar. Ancak bir de değer döndüren fonksiyonlar var ki, bunlar programlamada değer döndürmeyen fonksiyonlara kıyasla daha fazla yeri olan fonksiyonlar. Bu tür fonksiyonları tanımlamak için yine Fonksiyon Yöneticisi'nden "Ekle" tuşuna basıyoruz.


Fonksiyon ekleme menümüzde fonksiyonumuza bir isim verip (ben returnInt verdim, siz farklı verebilirsiniz) dönüş türünü belirliyoruz. Bu örnek için ben Integer türünden değer dönen bir fonksiyon oluşturmayı tercih ettim. Boolean, Integer, Real veya String bir değer döndürmeyi seçtikten sonra bir de fonksiyonun bu değeri hangi değişken aracılığıyla döneceğini yazıyoruz, burada değişken ismi tamamen bize bağlı. Ben anlaşılması kolay olsun diye "output" girdim. returnInt fonksiyonumuz bu işlem tamamlandıktan sonra şu şekilde oluşturulacak:

Bir değer döndüren fonksiyonlar, Flowgorithm'de bir değişken ve bu değişkeni döndürme bloğuyla birlikte tanımlanır. Bu değişkenin türünü "Declare" bloğundan, değişkenin değer döndürüp döndürmeyeceğini de fonksiyonun başlangıç veya sonuç bloklarından birisine çift tıklayarak değiştirebilirsiniz. Bu değişkenin değer döndürmesini sağlamak için Declare bloğunun altındaki oktan bir atama bloğu ekliyorum ve output'a bir değer giriyorum.



Değişkenimizin döndürdüğü değeri alıp kullanabilmek veya yazdırabilmek için ise fonksiyonu bir atama bloğuna veya çıktı bloğuna parametre olarak eklememiz gerekiyor. Ancak değişkenlerden farklı olarak fonksiyonun adını sadece ismiyle yazamıyorsunuz. Hem fonksiyonları değişkenlerden ayırmak, hem de alacağı parametreleri fonksiyonun kullanımında belirlemek için fonksiyon adından sonra parantez kullanılmaktadır. Parametre almayan fonksiyonlar boş parantezle yazılırken, parametre alan fonksiyonlar parantez içerisinde sırayla virgülle ayrılmış değerlerle birlikte yazılmaktadır.

  • Parametre almayan bir fonksiyon = fonksiyon1()
  • Parametre alan bir fonksiyon = fonksiyon2(parametre1,parametre2,...)
returnInt fonksiyonumuz parametre almadığı için kullanılırken returnInt() şeklinde yazılır.

Değer dönen fonksiyonları değer dönmeyenler gibi bir "çağırma" bloğuyla çalıştırmak zorunda değiliz. Atama veya çıktı yazdırma fonksiyonlarında bu fonksiyonları parametre olarak verdiğimizde bu fonksiyonlar çalışacak ve bu fonksiyonların döndüğü değeri almış olacağız. helloWorld fonksiyonumuz halihazırda "Hello, World!" yazdırıyordu, dolayısıyla biz bu programı çalıştırdığımızda karşımıza şu sonuç çıkacak:


Programımız 6 değerini döndürmek üzere tanımlanmış olduğundan dolayı bu değeri Output bloğunda yazdırdığımızda çıktı ekranında böyle bir sonuç alıyoruz.

Fonksiyonlar, çağırıldıkları andan itibaren tıpkı ana program gibi çalışırlar. Bu bakımdan ana programınızın birer uzantısıdırlar. Özellikle çok satırlı ve sık sık tekrar edilmesi gereken işlemler olduğu zaman hem programın kaynak kodunu kısaltıp daha okunabilir bir hale getirmek, hem de bakımını ve üstünde değişiklik yapmayı kolaylaştırmak için oldukça kullanışlıdırlar. Örneğin 10 satırlık bir algoritmayı gerekli olduğu bütün alanlarda olduğu gibi yazmak yerine sadece bir fonksiyonun içine yazıp gerekli olduğu alanlarda o fonksiyonu çağırmak yazılım geliştirme ve algoritma yazma alanlarında son derece yararlıdır. Ancak bu yazıda anlattığım parametresiz fonksiyonlar, bu yapının tüm gücünü yansıtmamaktadır, çünkü parametreler aracılığıyla sonuçları farklılaştırma ve programınızın üretebileceği çıktı sayısını çeşitlendirme imkanınız bulunmaktadır.

Parametre Alan Fonksiyonlar


Bu yazıda son olarak parametre alan fonksiyonların nasıl çağırılıp kullanıldıklarından bahsetmek istiyorum. Bunu da bir başka basit örnekle yapalım; bir sayının karekökünü alan bir program. Bu programın ilk kısmını şöyle oluşturuyoruz:



Programımızın başında tanımladığımız "val" değişkenini parametre olarak alan bir fonksiyon yapacağız. Bunun için Fonksiyon Yöneticisi'nde "SQRoot" isimli "Real" türünden bir değer dönen bir fonksiyon oluşturuyoruz.




Fonksiyon oluştururken menüdeki "Parametreler" alt başlığındaki "Ekle" butonuna tıkladığımız zaman parametre ekleme menüsü açılıyor. Bu menüde tıpkı değişken tanımlar gibi türünü ve dizi olup olmadığını belirleyerek bir parametre tanımlıyoruz. Program içerisinde okunabilirliği kolay olsun diye ben bu parametrenin ismini de "val" yapıyorum. Bu bir best practice (en iyi kullanım) olarak yazılım dünyasında yer alan bir uygulamadır.

Tanımlandıktan sonra SQRoot fonksiyonumuz

Fonksiyonumuz tanımlandıktan sonra gerekli işlemleri yapabiliriz artık. Bir sayının karekökü sayı^(1/2) olduğuna göre biz burada output değişkenine bu şekilde bir atama yapacağız. Ancak negatif sayıların karekökü tanımsız olduğu için girilen val değişkenini kontrol etmemiz gerekecek. Ben bu fonksiyonumuzu aşağıdaki şekilde tamamladım:



Fonksiyonda parametre olarak tanımlanmış olan val, 0'dan büyük olup olmadığı kontrol edilerek, büyük olduğunda 0.5 üssü alınarak döndürülecek şekilde kullanılmıştır. Yanlış olduğunda ise program bir hata mesajı döndürerek output değişkenine hata durumunda alabileceği bir değer (-1) atamıştır. Bu değerin hiçbir karekök tarafından elde edilemeyeceği hesaba katılırsa bu değer oldukça güzel bir hata belirteci olabilir. Bu kontrolü fonksiyon dışında da yapmanın bir yolu var, o da size ufak bir alıştırma olsun :)

Fonksiyonlara giriş yazımız, yani helloWorld() fonksiyonumuz bu şekildeydi. Bu fonksiyonun parametresi olarak verdiğim bilgilerin çıktı olarak anlaşılmış bir konu döndürdüğünü ümit ediyorum. Bir sonraki yazıda, yazılımda kendine yer edinmiş bir uygulama olan rekürsif (geri dönüşlü) fonksiyonları ve bir arkadaşımın tavsiyesi üzerine Divide and Conquer (Böl-Parçala) algoritmasını anlatacağım ve seride çıtayı yükseltmiş olacağım. İyi algoritmalar :)

Eğer bu seriyi faydalı bulduysan yeni yazılar geldiğinde haberdar olmak için buradan blogumu takibe alabilirsin.

Yorumlar

Bu blogdaki popüler yayınlar

Algoritmaya Giriş #8 - Özyinelemeli Fonksiyonlar

Algoritmaya Giriş #6 - Döngüler

Algoritmaya Giriş #4 - Diziler