Hangi Dili Seçmeli?

Bir sonraki bilgisayar kuşağında BASIC yerine Pascal'ın ön plana geçeceğini düşünen uzmanların sayısı gitgide artıyor. O halde, bu diller hakkında daha fazla bilgi sahibi olmakta yarar var.

Belçika'da göstericilerin sokağa dökülmeleri bir hükümet bunalımına yol açtı; hattâ Hindistan'da ölümle sonuçlanan olaylar çıktı; Alman yüksek öğretim kurumlarında ise akademik bir bayrak altında amansız ve çılgınca bir mücadele başlatıldı. Her üç olayın temelinde de aynı neden yatmaktaydı: Dil ile ilgili bir kavgaydı bu. Ancak, Belçika'da ve Hindistan'da patlak veren olaylarda halkın hayati önem taşıyan çıkarları gündeme gelirken, Almanya'daki gösterilerin odak noktasında, bilgisayar dersinde hangi programlama dilinin daha uygun olduğu sorunu yer almaktaydı. Bu kavgayı bugüne değin hiçbir taraf kazanamadı. Doğrusu da budur; çünkü en iyi dil diye bir şey yoktur. Dillerden bazılarının belirli bazı amaçlar için daha uygun oldukları söylenebilir olsa olsa. Biz bu konuda asıl neyin önemli olduğunu göstermeye çalışırken, uzun kuramsal tartışmalara girmek yerine, somut örneklerden yola çıkmayı tercih ettik. Bu nedenle de, sizlere sunmak üzere ele aldığımız bazı karakteristik programlama problemlerini, bilinen üç programlama dilinde çözmeyi uygun gördük. Niçin BASIC, Pascal ve LOGO? diye soracaksınız. Bunun nedenlerini şöyle sıralamak mümkün: Çünkü mikro-bilgisayar alanında en yaygın olan ve hemen her ev-bilgisayarı sahibinin ilk el attığı dil BASIC'tir; çünkü Pascal birçoklarınca, algoritma işlemlerinin öğrenilmesinde uygun bir dil olarak kabul edilmekte ve profi-programlar alanında zevkle kullanılmaktadır; çünkü LOGO “çocuk dili”nin beraberinde getirdiği zevksizliği üzerinden atmıştır artık... Son derece basit bir örnekle konuya girelim. Diyelim ki, bir veri-yönetim sistemi kurmak istiyoruz ve bunun için bir veri dosyasına gerek duymaktayız. Bu veri dosyası bir firmanın çalışanları ile ilgili olsun ve şu

Başlamadan önce bir taslak yapmalısın...

DIM A$(20)
ve iki
FOR-döngüsü

Buldum! İşe sistematik olarak el atmamız gerekiyor

Bir taslak, bir akış diyagramı

Öylece yazıyorum

Dur bakalım! Programlama dilin uygun mu acaba?

Şimdi biraz etraflıca düşünelim.

Dosya yönetimi ve biraz grafik...

Komutları biliyor musun? PENDOWN, HİDETURTLE, FORWARD 100...

bölümleri içersin: Soyadı, Adı, Doğum tarihi, Posta kodu, Yer, Sokak, ilgilinin devamlı mı, geçici mi çalıştığı ve devamlı statüde ise, ücreti.

Böylece bilgisayarın başına geçtiğimi ve programı yazdığımı düşünün. Programı yazma, yanlış aramalarla ve düzeltimlerle birlikte, yaklaşık iki saatimi alıyor. Daha önceden hiçbir taslak yapmıyorum ama böyle bir lüksü ancak küçük programlarda ve zamandan tasarruf etmek amacıyla kendime tanıyabilirim. İşte şimdiden BASIC'in temel özelliklerinden biriyle tanışmış oluyoruz: Bu sevimli çevirici-dilde olduğu gibi, bu kadar kısa bir süre içinde hatasız ve kendi gereksinmelerine uyarlanmış küçük bir program herhalde başka hiçbir programlama diliyle yazılamaz. Öte yandan, programın kuruluşunun bir ba-

ayatta hiçbir

şeyin ideali olmadığı gibi, bilgisayar dillerinin de ideali yok. Seçilecek dil, yapılacak işe, beklentilere, hattâ zevke bağlı.

kışta kavranamamasından doğan tehlikenin bu denli büyük olduğu bir başka programlama dili de yoktur. Bu noktada ona en çok yaklaşan diller Assembler ve Forth ve C gibi, Assembler benzeri dillerdir.

Pascal hayranı olan bir mesai arkadaşım bu programı önce Pascal diliyle yazdı. Her iki mini-programı karşılaştırdığınızda, iki şey hemen gözünüze çarpacaktır kuşkusuz: Pascal versiyonu 1) çok daha uzundur, 2) bir bakışta çok daha kolay kavranabilir.

Pascal'ı güçlü kılan özelliklerden biri -ki bunu herhalde bilirsiniz- onun “yapısallaştırma” yetisidir. Bu program-yapısı daha dökümde, yani programın simgesel ifadesinde apaçık görülür. Bu sayede, daha sonra yapılan düzeltimlere ve katkılara kolaylık sağlanmış olmaktadır. Böylece, karmaşık tarzda programlar da okunabilirliklerini korumuş olurlar. Ayrıca, Pascal'ın pedagojik etkisini de küçümsememek gerekir: Pascal, dakikliğiyle ve her değişkenin kullanımdan önce tam olarak açıklanmasını şart koşmasıyla, programcıyı disipline ve özene zorlar. Peki “yapısallaştırma” uygulamada ne anlama gelmektedir? Bir gün şöyle bir deney yapmak zahmetine katlanmıştım: İçlerinde belli bir değerin hesaplandığı program satırlarını, yabancısı olduğum bir BASIC programında aramaya çalışıyordum. Bir süre geçtikten sonra üzülerek gördüm ki, satırlar programın tümüne dağılmışlardı. Buna GOTO ve GOSUB komutları yol açmıştı. Gerçi GOTO komutu Pascal'da da var, ama orada pek makbul sayılmıyor ve birçok durumda da zaten gereksiz. Bunlar orada bloklar halinde çalışırlar ve bloklar içindeyse gerçekten birbirlerine ait olanlar bir araya getirilmişlerdir. Bu tür bloklar ya yordamlar (procedure) ve fonksiyonlardır (bunları “adları olan alt-programlar” olarak tanımlamak mümkündür), ya da bir “begin” komutuyla başlayan ve bir “end” komutuyla sona eren başka program birimleridir. Profesyonel bir Pascal-programının oldukça tuhaf bir görünümü vardır. Programın ilk %90'ı sadece tanımlar içerir; değişkene, yordamlara ve fonksiyonlara ilişkin tanımlar... Asıl program ise, içlerinde bu yordamların harekete geçirildiği birkaç satırdan oluşmaktadır. Böylelikle, programın okunmasına yüksek bir düzeyden -ana program düzeyinden-

Sonuç bu kadar büyük olmalı...

başlanabilmektedir. Daha sonra da ve ancak tedrici olarak programın diğer bölümlerine nüfuz edilebilmektedir. Tabii bunun tersi bir yöntem de geçerlidir: Programlamada ilkin programın kaba bir taslağıyla işe başlanmakta ve programa yavaş yavaş incelik kazandırılmaktadır. Buna “Top-Down” yöntemi denilmektedir. Adından da anlaşılacağı üzere, bu yukardan aşağıya doğru uygulanan bir yöntemdir. Ama “yapısallaştırma” sadece program yapısıyla sınırlı olmayıp bütün veri tiplerine yayılabilir. Böylece Pascal, BASIC'de bulunan verilerin ötesine geçmenin sözkonusu olduğu her yerde uygun bir programlama dili olarak sunar kendini bize. Örneğin doğum tarihi için bunu söyleyebiliriz: BASIC'de doğum tarihini ya üç sayıya ayırmak, ya da bu tarihi sözkonusu üç sayının kendisinden güçlükle çıkarıldığı bir karakter zinciri olarak işlemek zorunluğu vardır. Pascal'da ise üç rakamdan oluşan “Tarih” adlı yeni bir veri tipini tanımlamaktan başka bir şey yapmaya gerek yoktur. Bu arada, anılan üç rakamdan her birinin belli sınırlamalara tâbii olduğunu belirtmek gerekir. Böylece, doğum tarihi daha anlaşılır olmakta ve daha kolay okunabilmektedir. Bu sayede ayrıca, programdaki bazı işlemler daha kısalmakta ve hızlanmaktadır. Ele aldığımız örnekteki veri yığını da böylelikle temel veri tiplerinin bir araya getirilmesiyle oluşmuş bulunuyor: Tam sayılar, ondalık sayılar (REAL), karakterler (CHAR), karakter zincirleri (STRING) ve mantıksal değişkenler (BOOLEAN). Bunların dışında başka her şeyi kendi gereksinmelerinize göre ve kendi kendinize oluşturmanız mümkündür. Ama ben BASIC-sever bir kişi olarak Pascal'ın yolaçtığı güçlükleri düşünmeden edemiyorum. Bu dil pek çok alanda fazla muğlak geliyor bana. Kendi BASIC programlarımı zengin ve anlaşılır açıklamalar sayesinde her zaman okuyabiliyorum. Nasıl bir disiplin uygulanması gerektiğini de, bana dikte ettirilmesindense, kendi

sen de bir dil düşün

bilgisayarla

yapılmasını istediğimiz işin niteliği kadar, çalışma tarzımız da dil seçiminde etkili oluyor.

dil belirlemeyi tercih ediyorum. Ayrıca, Pascal'daki tipler zorunluluğunun sıkılığı kimi zaman gerçekten eziyetli oluyor. Sonuç olarak bir sayının INTEGER mi (tam sayı) yoksa REAL mi (ondalık sayı) olduğunu bazen bizzat bilgisayar belirlemelidir. Hem zaten o bunu benden daha iyi yapabilir. Tiplerin örneğimizdeki gibi güzelce bildirilmiş olmasına gelince, eğer bu bana bir avantaj sağlamıyor-

İşte buldum! Rekürsif bir sarmal çizeceğim.

sa ne yararı vardır bu bildirimin? Çünkü belirlenen sınırlar dışında bilgisayara veri aktarılması gene de mümkündür ve Pascal hiçbir hatayı bildirmemektedir. Yalnızca Pascal derleyicisi (Compiler) bu konuda bir avantaj sağlayabiliyor; çünkü bu sayede kendi depo alanı düzene sokulabilmektedir.

LOGO'NUN BÜYÜK GÜCÜ: RECURSION Bir keresinde bizim yazı kurulumuzda -başlangıçta çocuklar için geliştirilmiş- LOGO programlama diliyle ilgili olarak şiddetli bir tartışma çıkmıştı. Taraflardan biri LOGO'nun bütünüyle BASIC'le ya da Pascal'la kıyaslanabileceğini, dolayısıyla da LOGO ile yararlı programlar yapılabileceğini öne sürüyordu. Öbür grup ise hâlâ “çocuksu” olduğunu ve bu yolla -güzel grafik çizimler dışında- aklı başında hiçbir şey yapılamayacağını iddia ediyordu. Bu tartışmada herhangi bir çözüme ulaşılamadı. Biz de örnek programımızı LOGO dilinde yazmaktan kaçındık. Giriş/Çıkış rutinlerini ve veri yönetimlerini programlamak çok zahmetli bir işti. Çünkü bu dilin gücü, ona kız kardeşi LISP'ten (“yapay zekâ” için öngörülen programlama dili) miras kalan bir özellik olan “recursion”dan kaynaklanmaktaydı. (Recursion Pascal'da da vardır.) Bir ağaç resmi çizmek istediğinizi düşünün. Önce 10 cm. uzunluğunda bir cetvel alın ve bir çizgi çekin. Daha sonra cetveli, diyelim yarı yarıya, kısa tutun, biraz döndürün ve işleme baştan başlayın. Bu işlem, bizim herhangi bir yerde bir sona ulaşıncaya değin gitgide küçülen değerlerle sürekli olarak tekrarlanmalıdır. (Çizimin nerede son bulacağını tabii sizin yerleştirmeniz gerekiyor programa.) Gerçi şimdiden recursion'un özüne değin (aynı olayın sürekli tekrarlanması) bir fikir sahibi olduğunuz söylenebilir, ama tek başına bu kadar bilgi elbette yeterli değildir. BASIC'deki her FOR-NEXT de bunu pekâlâ yapabilir. Recursion'un önemli bir özelliği şudur ki, bilgisayara iletilen bir komut hemen uygulanamamakta, aynı şemaya göre bir dizi alt-komutun çözülmüş olması gerekmektedir. Bunu somutlaştırmak için şöyle bir durumu gözünüzün önüne getirin: Bir dostunuz size geliyor ve bir bilgisayar edinmek istediğini bildiriyor. Ama amatör telsizci olan dostunuz bu hobisinden dolayı mutlaka özel bir program arzu ettiğini de sözlerine ekliyor ve size bu konuda kendisine bir tavsiyede bulunup bulunamayacağınızı soruyor. Siz herhangi bir tavsiyede bulunamıyorsunuz. Bununla birlikte, sizin de bilgisayar ticareti yapan bir tanıdığınız vardır ve bu kişiye amatör telsizciler için özel programı olan bir bilgisayar bilip bilmediğini soruyorsunuz. Ama o da yardımcı olamıyor bu konuda, ancak onun da danışacağı yetkili birisi vardır... vb. En sonunda bu konuda bilgi sahibi olan birini bulmak mümkün oluyor. Bu kişi doğrudan kendisine

BASIC

READY.
100 REM VERİ KAYITLARI
110 DIM AS(8),B$(8)
120 FOR 1-1 TO 8:READ
130 DATA “AD”,
“SOYAD”, “DTARIH”,
“SOKAK”, “SEMT”,
“SEHİR”,
140'PRİNT
TAB(10);
:PRİNT
TAB(10);
1 TO 8:PRİNT
150 FOR |
BS0):
NEXT
READY.

Kısa ama karışık: BASIC'de veri soruşturması.

BR Logo

TO S :X :ORD
REPEAD 4 ICIZ :X :ORD
SAGA END
END
TO CIZ :X :ORD
IF :ORD — 1 THEN
FORM :X STOP
CIZ :X :ORD — 1 SAGA :X
CIZ :X :ORD — 1 SOLA :X
CIZ :X :ORD — 1 SAGA :X
CIZ :X: ORD — 1
END
TO FORM :X
REPEAT 2 :X
LEFT 45)
FORWARD :X
END
TO SOLA :X
LEFT 45
FORWARD :X
LEFT 45
END
TO SAGA :X
RIGHT 90
FORWARD :X
RIGHT 90
END

ilişkin LOGO programı dört adet alt-rutine (SAGA, SOLA, FORM, CIZ) ve bir adet ana yordama sahip (5).

PASCAL

program dosya;
type tarih - record gün:
ay:
yıl:
end;
adres - record ad:
soyad:
dogum:
yer:
semt:
sokak:
case denk:
true:
false;
end;
var düzeltici: adres;
sahte; stringl801;
begin writeln (
writeln (
with duzeltici do
begin
write (ad.....
(ad);
1..12,
1890..2000;
stringl801;
stringl801;
tarih;
1000..8999;
stringl801;
stringl801;
boolean of
(geçici: real);
bilgi girisi

Buna tekabül eden Pascal programının uzun olduğu açık, ama ilk bakışta kavranması da çok daha kolay.

başvurmuş olana gerekli bilgiyi veriyor, bu bilgiyi alan da kendi tanıdığına bunu aktarıyor, o da öbürüne, tâ ki dostunuzun sormuş olduğu şey kendisine ulaşıncaya kadar. Recursion mekanizması en basit durumda böyle işlemektedir. Ama örneğin bir kitabın çözümlenmesi söz konusu olduğunda karmaşık durumlar ortaya çıkabiliyor. Kitap önce bölümlere, bölümler cümlelere, her bir cümle dil bilgisel kategorilere, her kategori alt-kategorilere, her alt kategori kelimelere, her kelime hecelere ve her hece de harflere ayrıştırılıyor. Ayrıştırma süreçlerinin hepsi birbirine benzemektedir. Ama bir ayrıştırma işlemi her zaman ânında tamamlanmamakta, muhtemelen de bir sonraki evrenin çözümlenmesine bağımlı kalmaktadır. LOGO'nun somut diline çevrildiğinde bunun anlamı şudur: En basit rekürsif fonksiyon -belki de okul dönemlerinden hatırlayacağınız- faktöriyel işlemdir. Bu işlem, sayının ardından gelen bir ünlem işaretiyle ifade edilmektedir: 3!=1x2x3=6. Ancak, rekürsif olarak bu fonksiyon şöyle tanımlanmaktadır: N sayısının faktöriyeli, ilkin N-1'in bulunması ve bunun da N sayısı ile çarpılması yoluyla hesaplanmaktadır. Bunun içinse tabii önce (N-1)! sayısının bilinmesi gerekmektedir ki, bu da (N-2)'den çıkarılmaktadır... vb. Ta ki 1'e ulaşıncaya kadar. Çünkü matematikçiler 1'in faktöriyel değerinin 1 olduğunu saptamışlardır: 1!=1. LOGO'da ise bu şöyle ifade edilmektedir: TO FAK :N IF :N=1 THEN OUTPUT 1 STOP ELSE OUTPUT :N * FAK (:N-1) Bu formülü şöyle açıklayabiliriz: Burada “N” N'in değeridir. “OUTPUT” ise bir şeyin geri verileceğini göstermektedir. Çünkü her LOGO yordamı tek bir görevi yerine getirir. Bu görevi dolaysız olarak yerine getiremediği takdirde, komutu bir alt programa iletir. Bu alt-program söz konusu komutun yordam tanımını temin eder ve sorunu çözmeye çalışır. Eğer başarılı olamazsa, o da tıpkı bir önceki gibi yaparak komutu bir alt-alt programa aktarır. Bu işlem, komut vericilerinden biri istediği sonucu alıncaya kadar böylece sürüp gider. Bu durumda sonuç bir önceki komut vericiye iletilir (OUTPUT talimatı aracılığıyla). Bu da bir kez daha görevini yerine getirmeyi dener.

Bunda başarılı olduğu takdirde, elde ettiği sonucu kendi komut vericisine (yukarıya) aktarır... vb. En sonunda ise, eğer bütün komut vericiler kendi görevlerini yapmışlarsa, LOGO basıma geçebilmektedir. Bu anlatılanlar karmaşık mı geliyor size? Öyle olsa da, kaygılanmanıza gerek yok. Çünkü “recursion” veri işlemin en tuhaf ve güç anlaşılır kavramlarından biridir. Bilgisayarın bütün hesap işlemlerine saydam bir şekilde ışık tutacak basit bir örnekle konuya açıklık getirmeye çalışalım: Örneğin, 3 sayısının faktöriyelini hesapladığımızı düşünelim. Bu durumda LOGO ilkin N=1 olup olmadığını sorar. Yanıt olumsuzdur. O zaman yordam (buna “1” diyelim) 3 değerini kaydeder ve bir alt-yordamı 3 faktöriyelini bulmakla görevlendirir. “2” olarak adlandıracağınız yordam ise N=1 olup olmadığını yoklar; yanıt olumsuzdur ve yordam “2” bu defa 2 değerini kaydederken bir alt-alt-yordamı 2-1=1'in faktöriyelini bulmakla görevlendirir. “3”te N'in değerinin 1 olup olmadığını sorar; yanıt olumludur. Bu durumda yordam “3” büyük bir gururla yordam sonucunu aktarır. Şimdi yordamın kullanabileceği bir değeri vardır ve bunu 1x2=2 şeklinde kullanır. Bu sonuç ilk komut vericiye iletilir ve böylece o da tıpkı bir önceki gibi işlem yapabilecek bir değer edinmiş olurken bu (2) değerini kendi değeri olan (3) ile çarparak 6 sayısını bulur. Buysa, görüldüğü gibi, 3 sayısının faktöriyelidir: 3! Şimdi artık önemli olanın ne olduğunu herhalde daha iyi anlaşılmaktadır: Sorun bizzat çözülemediğinde, görevi bir başkasına aktarmak. Bunun temelinde yatan ilkeyi “gecikmeli uygulama” olarak nitelendirmek mümkündür. Burada bütün ara değerler ve ara formüller depolanmak zorundadır ve bundan ötürü de rekürsif diller çok fazla bellek hacmi gerektirirler. LISP'in, ev ya da kişisel bilgisayarlarda bu denli ender görülmesinin nedenlerinden biri de budur. Ama depolama konusunda programcının kaygıya kapılmasına hiç gerek yoktur; çünkü bütün bunları LOGO-çeviricisi üstlenmiştir. Recursion'un ardında yatan ilke grafik olarak pek güzel gösterilebilir -“çocuk” dili LOGO'nun eğitsel yönden taşıdığı büyük değerin kaynağını da burada aramak gerekir. Bir örnek daha verelim: Geçen yüzyılın sonlarına doğru bazı matematikçiler son derece garip görünümlü birtakım eğriler keşfettiler. Bu eğrilere akademik çevrelerce “patalojik” damgası vuruldu. Çünkü bunlar, eğrilere ilişkin peşin yargıları altüst etmişlerdi. Söz konusu “hastalıklı” eğriler bulundukları yüzeyi en sonunda baştan başa kaplıyorlardı; çünkü çok sık bir dallanma sürecine giriyorlardı. Öyle ki, her alt dal, dallanma sırasında yeni bir alt dal ve bu da başka bir alt dal... vb. oluşturuyordu. Tıpkı recursion'da olduğu gibi. Bu yeni oluşumlar hiç de salt birtakım oyunlar sonucunda ortaya çıkmış değillerdi; birçok alana yeni bilgiler kazandıran ve olağanüstü bilgisayar grafiklerine imkân veren bir bilimin gelişmesi bu eğriler sayesinde olmuştur. Biz bu eğrilerden biri üzerinde çalışmaya başladık (“Sierpinski-eğrisi”, adını bulucusundan almıştı). Eğriyi LOGO dilinde göstermeye uğraşıyorduk. Ben bir gün sonrasında sinirlerim harap olmuş bir durumda bu işten vazgeçerken, meslektaşım Lehmann, çalışmasını yılmadan sürdürdü ve rekürsif hilelere karşı yürüttüğü toplam 24 saatlik bir mücadele sonucunda basit görünümlü bir program yapmayı başardı. Gerçekten de, LOGO'nun temel sözlük dağarcığına egemen olan herkes bu programı (anlamasa bile) “okuyabilirdi”. Ama kendi düşüncesi hakkında da düşünebilmek, insan zekâsının bir özelliği. Yapay zekâ dilleri bu özelliği Recursion aracılığıyla taklit eder.

Planlanır ve denenirse bu görünüm çıkıyor ortaya.

aynı program BASIC'de öylesine kapsamlı ve bir bakışta anlaşılması öylesine zordu ki, burada bunun dökümünü yapmaktan kaçınmak zorunda kaldık.

Ayrıca, Pascal ile LOGO arasında bir karşılaştırma yapmaktan da çekindik. Çünkü LOGO'nun tipik grafik yetenekleri Pascal'da ya hiç yoktu, ya da aynı şekilde mevcuttu. Bu durum versiyona bağlı olarak değişiklik gösteriyordu. Bu dilin ilk taslağında hiçbir grafik imkânı öngörülmemiştir. Bütün bu anlatılanlardan sonra, sizin için hangi dilin en uygun dil olduğuna bilmem karar verebildiniz mi? Eğer veremediyseniz cesaretiniz kırılmasın. En iyisi, kişinin bunu bizzat denemesi ve mizacına en uygun düşen dili sonunda kendi kendisinin seçmesidir. Programlama dillerinin seçimiyle araba ya da bilgisayar seçimi arasında pek fazla bir fark yoktur.