LOGO Öğreniyoruz (6)
Retro bilgisayarArtık adet haline geldi: İki sayıda bir, işe bir önceki sayıda yer alan hataları düzeltmekle başlıyoruz. Üstelik bu seferki de nispeten ciddi. Geçtiğimiz sayıda verdiğimiz ve güneş şeklini tasarlamak için geliştirilmiş işlemle, istediğimizi elde edemeyiz. Daha doğrusu, bir güneş şekli elde ederiz ama bu, renkli olmaz. Sebebi basit. İşlem üzerinden ilk geçişte bilgisayar REPEAT 72 komutuna rastlayacak ve bunu izleyen komutların ise parantez içinde (PC :X+1 DORTGEN RT 5) komutları ile karşılaşacaktır. PC'nin değerini 1 artırdıktan sonra, 72 kere, parantezin dışına çıkmadan, onu izleyen işlemleri yerine getirecektir. Yani, DORTGEN'i 5'er derece sağa kaydırarak 72 kere çizecektir. Ondan sonra da parantezin dışına çıkacak ve END komutu ile karşılaşıp sona erecektir. Dolayısıyla, REPEAT 72 komutuna rağmen, çizgilerimizin rengini belirleyen PC'nin değeri ancak 1 kere artırılmış olacaktır. Dolayısıyla da, alacağımızı söylediğimiz, PC DOESN'T LIKE 16 AS INPUT mesajını almayacağız.
Kendi Üzerine Dönen Kaplumbağa
Bu hata mesajını almak ve renkli bir güneş çizmeye, hiç değilse başlamak için, bütün diğer yapay zekâ dilleri ile birlikte LOGO dilinin de en önemli özelliği olan, “kendi üzerine dönüşlülük” (recursivity) özelliğinden yararlanmamız gerekiyor. Başka bir deyişle, işlemimizin çalışırken kendi kendine gönderme yapması, yani kendi kendini çağırması gerekiyor. Şöyle,
YO GUNES
MAKE “X :X41
PC :X
DORTGEN RI 5
GUNES
END
Burada ilk dörtgen çizilip, kaplumbağa 5 derece sağa döndükten sonra her şey yeniden başlayacak, dolayısıyla da PC'nin değeri bir kere daha artırılacak, dörtgen bir kere daha çizilecek, kaplumbağa bir kere daha 5 derece sağa döndürülecek ve işlem yine kendi kendisini çağıracak ve ilh. (Kendi üzerine dönüşlülüğün mantığını daha iyi kavramak istiyorsanız, işlemi çalıştırmadan önce, TRACE yazın. LOGO size işlemin çalışmasının her evresini gösterecektir. Sıkıldığınızda da NOTRACE yazın.) İşlem kendi kendisini 15 kere çağırdığında :X'in değeri 1, dolayısıyla da PC'nin değeri 16 olacaktır. İşte bu noktada da LOGO size PC DOESN'T LIKE 16 AS INPUT, yani PC girdi olarak 16'yı beğenmiyor, diyecektir. Bu durumu düzeltmek için gereksindiğimiz koşullu komutu nereye yazacağımız açık olmalı: (Karışıklık olmasın diye bu düzeltilmiş işlemi GÜNES2 diye adlandıralım):
TO GUNES2
IF :X—15 THEN MAKE “X 0 ELSE PC :X
DORTGEN RI 5
GUNES
END
LOGO Öğreniyoruz (6)
Artık her şey tamam. Yalnız dikkatinizi çekmek istediğim bir nokta var. Farkındaysanız, daha önceki kusurlu versiyonumuzdaki 72 sayısını burada kullanmadık. Bunun bir sonucu, işlemimizin sona eriş koşulundan yoksun kalmasıdır. Dolayısıyla, biz kendisini CTRL-G tuşlarına basarak durdurmadığımız takdirde, sonsuza dek sürüp gidecektir. Kuşkusuz bu durum, işlemin kendi kendisini kaç kez çağıracağını belirleyecek bir sayaç değişkeni kullanan bir koşullu komut ekleyerek giderilebilir. Bu geliştirmeyi size bırakarak, ikinci düzeltmemi yapayım. Geçtiğimiz sayıda “eğer herhangi bir LOGO komutu, parametre olarak sayısal bir değer alıyorsa, bir hesaplama da olabilir” demiştim. Bunu derken, vallahi, el kitaplarının yalancısıydım. Ama o zamandan bu yana gördüm ki, bazı LOGO değişkenlerine, örneğin çizgilerin rengini belirleyen PC değişkenine, her zaman hesaplama yoluyla değer atfetmek mümkün olmuyor. Örneğin, etkileşimli tarzdayken PC 2+4-3 dediğinizde çizgilerin rengini değiştirmeyi başarıyor, yeşil bir kaplumbağa elde ediyorsunuz. Ama aynı şeyi bir değişken kullanarak yapmayı denerseniz, olmuyor. Yani önce MAKE “X 2 gibi bir komut verip, sonra PC :X+4-3 yazarsanız, hiçbir şey olmuyor. Artık hangi değişkenlerin, ne zaman parametre olarak hesaplama kabul ettiğini deneme yanılma yoluyla bulacağız. Bir de, bir yazım ya da pikaj hatası olduğunu sandığım bir hata var. “FD X komutunun sonucu, “X değişkenin (nesnesinin) X değerini almasıdır”” denmiş. Tabii değildir; kaplumbağanın X kadar ilerlemesidir. “A değişkenine X değerini veren komut MAKE “A X”'tir.
Logo'da Aritmetik İşlemler
Toplama, çıkarma, çarpma ve bölme gerektiren hesaplamaların doğrudan doğruya bu işlemlerin işaretleri tarafından yaptırıldığını biliyoruz. Bu yüzden, bunlar üzerinde fazla durmayacağız.
Bunların dışında sayısal bir parametre alan ve aritmetik bir hesabın sonucu olan bir çıktı üreten komutlar şunlardır:
ROUND :X.Y :X (gerçek bir sayıyı yuvarlar) Örnekler: ROUND 3.7 RESULT: 4 ROUND 3.4 RESULT: 3
INTEGER :X.Y :X (gerçek bir sayının tamsayılı kısmını verir) Örnekler: INTEGER 3.7 RESULT: 3 INTEGER 3.4 RESULT: 3
QUOTIENT :X :Y INTEGER (:X/:Y) (İki gerçek sayının bölümünün tamsayılı kısmını verir) Örnekler: QUOTIENT 7 2 RESULT: 3 QUOTIENT 1 2 RESULT: 0
Burada dikkat edilmesi gereken bir nokta, QUOTIENT'ın girdilerini önce ROUND işlemine tabi tuttuğudur.
Örnek: QUOTIENT 7.2 3.4 RESULT: 2 QUOTIENT 7.2 3.6 RESULT: 1
REMAINDER (İki tamsayının bölümünden kalanı verir) Örnekler: REMAINDER 7 2 RESULT: 1
REMAINDER'ın parametreleri olarak gerçek (ondalıklı) sayılar verilirse, aynen QUOTIENT'da olduğu gibi, bunlar da ROUND edilir.
SQRT (Karekök) Örnekler: SQRT 160 RESULT: 12.6491 SQRT 16 RESULT: 4
Aritmetik komutlar arasında bir de trigonometrik fonksiyonları sayabiliriz: SIN ve COS. SIN 0, çıktı olarak 0, COS 0 çıktı olarak 1 verir.
Tesadüfler Dosyası
Son olarak da, özellikle karmaşık işlemler yazarken diğer bütün aritmetik komutların çıktılarına sık sık başvurmak zorunda kalacakları bir çift aritmetik komutu görelim. Bu ikisi birarada bir rastlantısal sayı üretici olarak çalışır. Bunlardan birincisi RANDOM komutudur ve girdi olarak tamsayılı bir parametre gerektirir. RANDOM :X, çıktı olarak 0 ila X-1 arasında yeralan bir rastlantısal sayı verir. Peki, RANDOM komutu bu işi gördüğüne göre, rastlantısal sayı üreticisi olarak ikinci bir komuta niçin ihtiyacımız olsun? Bu sorunun ayrıntılı cevabını Commodore Dergisi'nin X. sayısında yeralan Rastlantısal Sayılar yazısında bulabilirsiniz. Burada şu kadarını söylemekle yetinelim: Diyelim ki, 0 ila 9 arasında bir rastlantısal sayı üreteceğiz. Bunu yapmak için bilgisayar bir “çekirdek” sayıdan yararlanır ve bunun üzerinde belli işlemler yaparak çeşitli sayılar üretir. Bu “çekirdek” sabittir. Dolayısıyla, iki ayrı seansta, arada Logo programını kapatıp yeniden çalıştırdıysanız, verdiğiniz RANDOM komutları aynı sayı dizilerinin üretilmesine yolaçacaktır. Bu ise rastlantıdan beklediğimiz şeye ters düşen bir durum. Bunu önlemek için rastlantısal sayı üretirken kullanılan çekirdeğe doğrudan doğruya müdahale etmemiz gerekir. RANDOMIZE komutu bunu yapmamızı sağlar. Komut yalnız başına da, bir parametre ile de kullanılabilir. Yalnız başına kullanıldığında çekirdeğin kendisi rastlantısal olarak tayin edilir. Bir parametre kullandığınızda ise, çekirdeği siz belirlemiş olursunuz. Bir parametre ile birlikte kullanılırken komutunun parantez içine alınması gerekir. (RANDOMIZE 28) gibi. Şimdi komutunun işlevini bir örnek üzerinde görelim. Bu örnekte üstüste bir dizi rastlantısal sayı çağıracağız ve aynı çağrıları birkaç kez tekrarlamamız gerekecek. Bu yüzden, ben kolaylık olsun diye şöyle bir işlem yazdım:
TO RAST REPEAT 4 |PRINT RANDOM 10|
REPEAT 4 |PRINT RANDOM T|
REPEAT 3 |PRINT RANDOM $8|
END
Buradaki sayılar önemli değil, isterseniz değiştirebilirsiniz. Önemli olan, RANDOM komutunu aynı parametrelerle ve aynı sıra içinde birkaç kere üstüste çağırmak. Şimdi herhangi bir parametre kullanarak RANDOMIZE komutunu verin. Ben (RANDOMIZE 28) komutunu kullandım ve RAST işlemini çalıştırdığımda şu sonucu elde ettim: 9 1 7 9 1 0 4 1 6 3 2. Şimdi yapmamız gereken herhangi bir başka parametre ile RANDOMIZE komutunu tekrar vermek. Bunun üzerine RAST komutunu verdiğinizde başka bir sayı dizisi elde ettiğinizi göreceksiniz. Ama şimdi tekrar (RANDOMIZE 28) komutunu verip çalıştırırsam yine ilk onbir sayı olarak, ilk baştaki aynı onbir sayıyı elde ediyorum: 9 1 7 9 1 0 4 1 6 3 2. Çünkü belli bir çekirdekten üretilen rastlantısal sayılar hep aynı sıra içinde üretilirler. Artık, geçtiğimiz sayıda vaad ettiğimiz, LOGO dilinin bütün aritmetik işlemlerinin sayımına geçiyoruz: Hatırlayacaksınız, geçtiğimiz sayıda, renkli güneş çizmenin iki yolu var, demiştik. Kolay ve dolambaçlı olandan kasdettiğimiz, bu bölümün başında gördüğümüz ve koşullu komutlarla, LOGO'nun dönüşlülük özelliğinden yararlanan çözümdü. İkinci çözümünse daha çok şey bilmeyi gerektirdiğini söylerken kasdettiğimiz RANDOM komutu idi. Artık yeni bir GÜNES işlemini, dönüşlülüğe ve koşullu komutlara hiç başvurmadan, şöyle yazabiliriz:
TO
REPEAT 72/PC RANDOM 16 DORTGEN RI 5|
END
Bu işlemde, 72 tekrarın her birinde, RANDOM fonksiyonu, 0 ila 15 arasında bir sayı üretecek (unutmayın, RANDOM X, 0 ila X-1 arasında bir rastlantısal sayı üretiyor) ve PC değişkenine aktaracaktır. GUNES3'ün GUNES2'ye kolaylığından başka bir üstünlüğü daha var. GUNES2'de renk değerlerini biz birer birer artırdığımız için, renklerin değişmesi hep aynı sırayı izleyecektir. Oysa, GUNES3'te renk değerleri rastlantısal olarak üretildiği için, sonuçtaki şeklimiz çok daha alaca olacaktır. Daha hatasız sayılarda buluşmak ümidiyle, bu ay da bu kadar. Hoşçakalın.