Python ve Haskell
Bu zamana kadar hep object-oriented programlama dillerinde çalışmış biri olarak Haskell’i ilk gördüğümde gerçekten çok ÅŸaşırdım. Haskell fonksiyonel bir dil. Yani programlarınızı deÄŸiÅŸkenler üzerinden atamalar yaparak deÄŸilde, matematiksel ifadeler olarak yazıyorsunuz. Tabi bazı özel durumlarda Haskell içerisinde de ufak atama benzeri iÅŸlemler yapmanız gerekebiliyor. Haskell’in kullandığı matematiksel ifadelere genel olarak lambda calculus deniliyor. Atama yapma olanağınız olmadığından iÅŸlemler genelde recursive olarak geçekleÅŸtiriliyor. EÄŸer sizde benim gibi fonksiyonel bir dile yabancıysanız gerçekten kafanız karışabilir.
Haskell’den haberdar olduktan sonra öğrendim ki bazı bilinen dillerde fonksiyonel programlamayı destekliyormuÅŸ. Bunların başında da tabiki hep imperative hemde object-oriented programlamayı destekleyen Python geliyor. Bunların dışında Python aynı zamanda fonksiyonel programlamayı da destekliyormuÅŸ. Fakat sadece Python deÄŸil, Microsoft Virsual Studio 2010 ile birlikte gelen F# dilide fonksiyonel programlamayı destekliyor. Hatta Java bile baÅŸka 3rd party kütüphanelerle fonksiyonel programlamayı destekliyor.
Öncelikle Haskell’i ve Python’u nasıl kuracağımıza bir bakalım. BaÅŸlamadan önce belirtmeliyim ki Eclipse Galileo kullanıyorum. Bundan dolayı ayrıca bir Haskell ya da Python geliÅŸtirme ortamı anlatmak yerine, Eclipse eklentileriyle bu dilleri Eclipse’de nasıl kullanılacağını anlatacağım. İşletim sistemi olarak da Ubuntu 10.10 x86 kullanıyor olacağım.
Kurulum
Eğer bu zamana kadar Eclipse kurmadısanız, bir an önce en güncel sürümünü indirip kurmanızı tavsiye ederim.
Ubuntu altında çalıştığımdan Python interpreter sistemimde zaten yüklü. Fakat baÅŸka bir iÅŸletim sistemi kullanıyorsanız Python interpreter’ı bu siteden indirebilirsiniz. Yeni inderecek olanlar için 2.7.xx versiyonu tavsiye ediliyor. Python 3 sürümüyle ilgili bazı problemler varmış bildiÄŸim kadarıyla fakat ne olduklarını bende tam olarak bilmiyorum. Interpreter’ımızı yükledikten sonra Eclipse eklentisini yükleyelim.
Åžimdi ise Eclipse IDE’si için PyDev eklentisini indirelim ve ayarlarını yapalım.
- Öncelikle Eclipse-> Help -> Install New Software … seçilir ve aÅŸağıdaki repository eklenir.
- http://pydev.org/updates
- Yüklenebilecek dosyaların bilgisi indirildikten sorna PyDev seçilir ve yüklenir.
- Åžimdi sadece PyDev eklentisine Python interpreter’ın sistem yolunun gösterilmesi kalıyor.
- Bunun için Eclipse-> Windows -> Preferences seçilir ve sol taraftan Pydev genişletilir
- Interpereter – Python seçilir ve Auto Config butonuna tıklanarak, Eclipse’in sizin için sistem yolunu bulması beklenir.
EÄŸer Eclipse sizin için sistem yolunu bulamazsa “usr/lib/” yoluna bakabilirsiniz. Python derleyiciniz yüklüyse bu yolun altındaki klasörlerde göreceksiniz.
Python ve Pydev yüklemesi bu kadar. Şimdi ise Haskell interpreter ve Eclipse eklentisinin nasıl yükleneceğine bakalım.
- Öncelikle aÅŸağıdaki komutu çalıştırarak GHC interpreter’ını yükleyelim.
- $ sudo apt-get install ghc6
- Ya da eğer çok kullanılar kütüphaneleri ile birlikte falan yüklemek isterseniz
$ sudo apt-get install haskell-platform
- $ sudo apt-get install ghc6
- GHC yüklendikten sonra sıra Eclipse eklentimize geliyor yani EclipseFP 2.0
- Yine Eclipse-> Help -> Install New Software … seçilir ve aÅŸağıdaki repository eklenir.
- http://eclipsefp.sf.net/updates ve 2.0.2 versiyonu yüklenir.
- Haskell içinde GHC’nin sistem yolunu vermemiz gerekiyor.
- Bunun için Eclipse-> Windows -> Preferences ve sol taraftan Haskell genişletilir
- Haskell Implementations seçilerek GHC’nin sistem yolu eklenir.
Benim makinem için sistem yolu “/usr/lib/ghc-6.12.1/bin”
Şimdi her iki programlama dilimizde Eclipse ortamlarıyla beraber kurulmuş oldu. Şimdi ise benim Advanced Programming dersinde gördüğüm ve Haskell: The Craft of Functional Programming, 2nd ed., Simon Thompson kitabında anlatılan örneğin bir benzerini anlatmaya çalışalım.
Satranç Atı
Kitapta bahsi geçen ASCII karakterlerle oluşturulmuş ve horse.txt dosyasında kayıtlı satranç atı resmini okuyan ve bunun üzerinde işlemler yapan bir örnek. Örnetteki at şu şekilde ve horse.txt dosyası içerisinde kayıtlı.
horse.txt
…….##…..
…..##..#….
…##…..#…
..#…….#…
..#…#…#…
..#…###.#…
.#….#..##…
..#…#…….
…#…#……
….#..#……
…..#.#……
……##……
Bu ÅŸekil üzerinde noktaların beyaz diyez iÅŸaretlerinin siyah olduÄŸunu varsayılım. İki tane fonksiyon ya da method yazılacak bir tanesi y eksenine göre tersine alacak bir taneside beyazları siyah, siyahları beyaz yapacak. Haskell’de ve Pythonda fonksiyonel programlama açısından bu iki iÅŸlemin nasıl yapıldığına bakalım.
Haskell
Haskelde öncelikle projemizi yaratmamız gerekiyor. Bunun için Eclipse -> New Project deyip, burdan Haskell project‘i seçiyoruz. Projemizin adı PictureInHs olsun. Daha sonra Haskell Perspective‘ini aktif hale getirip kodumuzu yazmaya baÅŸlıyoruz. Proje menüsünden kendi yarattığımız projeyi bulup src klasörürünün altına bakıyoruz ve Main.hs dosyasının zaten yaratılmış olduÄŸunu görüyoruz. Bu dosyayı aÅŸağıdaki gibi deÄŸiÅŸtiriyoruz
Main.hs
module Main where type Picture = [String] draw :: Picture -> IO () draw pic = (putStr . concat . map (++"n")) pic flipV :: Picture -> Picture flipV pic = (map reverse) pic invertPixel :: Char -> Char invertPixel c = if c == '.' then '#' else '.' invert :: Picture -> Picture invert pic = (map (map invertPixel)) pic main::IO() main = do horseData <- readFile "horse.txt" horse <- return (lines horseData) draw horse putStrLn "Vertical Flip" draw (flipV horse) putStrLn "Inverting picture items" draw (invert horse)
Daha sonra önceden yaratığımız horse.txt dosyasını, Eclipse içinde PictureInHs projesinin altına kopyalıyoruz. Projemizi “GHCi” olarak çalıştırdığımızda, konsolda bizden girdi bekleyen bir ekran göreceÄŸiz. Buraya main yazıp, çalıştırdığımızda, aÅŸağıdaki ekran çıktılarını görebileceÄŸiz.
Python
Åžimdi ise, yine fonksiyonel ÅŸekilde, hibrid bir dil olan Python altında nasıl yapacağımıza bakalım. Python’un hibrid özelliÄŸinide kullanmak için, öncelikle bir Picture Class’ı yaratalım ki bu bakımdan object-oriented olsun. Fakat istediÄŸimiz iÅŸlemleri yapacak olan fonksiyonları, fonksiyonel ÅŸekilde yazalım ve bunları ekrana bastıralım.
Bunun için öncelikle Eclipse -> New deyip, bir Python Project yaratalım. Fazedelim ki adı PictureInPy olsun.Bu seferde Pydev Perspective geçelim. Daha sonra projenin src klasörünün altına gelip bir Python Module yaratalım. Farzedelim ki bu modlun adıda picture.py olsun.
picture.py
# OBJECT-ORIENTED WITH FUNCTIONAL METHODS class Picture: def __init__(self, filename): f = open(filename) self.data = f.read().splitlines() f.close() def drawVertical(self): print('n'.join(self.flipV())) def drawInvert(self): print('n'.join(self.invert())) def draw(self): print('n'.join(self.data)) def flipV(self): return map(lambda line: line[::-1], self.data) def invert(self): return [''.join(map(lambda c: '#' if c == '.' else '.', line)) for line in self.data] print("\n Object Oriented with using Functional Methods \n") horse = Picture('horse.txt') horse.draw() print "Vertical Flip" horse.drawVertical() print "Inverting picture items" horse.drawInvert()
Şimdi daha önce hazırlamış olduğumuz horse.txt dosyasını, projemizin src klasörünün altına kopyalıyoruz.Hazırladığımız kodu çalıştırdığımızda aşağıdaki ekran çıktılarını elde edeceğiz.
Ekran Çıktıları
…….##…..
…..##..#….
…##…..#…
..#…….#…
..#…#…#…
..#…###.#…
.#….#..##…
..#…#…….
…#…#……
….#..#……
…..#.#……
……##……
Vertical Flip
…..##…….
….#..##…..
…#…..##…
…#…….#..
…#…#…#..
…#.###…#..
…##..#….#.
…….#…#..
……#…#…
……#..#….
……#.#…..
……##……
Inverting picture items
#######..#####
#####..##.####
###..#####.###
##.#######.###
##.###.###.###
##.###…#.###
#.####.##..###
##.###.#######
###.###.######
####.##.######
#####.#.######
######..######
Referanslar
Son olarak bu yazıyı hazırlarken yararlandığım kaynaklar
- Haskell: The Craft of Functional Programming, 2nd ed.
Addison Wesley, 1999, ISBN 0-201-34275-8 - Aldığım, İleri Programlama, dersimin kaynakları. SoruceForge
End Of Line