http://alikoker.name.tr



Benzer belgeler
Genel Programlama II

Sunum İçeriği. Programlamaya Giriş

1.1. Yazılım Geliştirme Süreci

Lambda İfadeleri (Lambda Expressions)

Programlama Dili Prensipleri. Lab Notları 8 ve 9

MAT213 BİLGİSAYAR PROGRAMLAMA I DERSİ Ders 1: Programlamaya Giriş

BMT 101 Algoritma ve Programlama I 11. Hafta. Yük. Müh. Köksal Gündoğdu 1

HESAP MAKİNASI YAPIMI

Merhaba değerli Dostlar;

KOD PARÇACIKLARI 1 / 5

FONKSİYONLAR. Gerçek hayattaki problemlerin çözümü için geliştirilen programlar çok büyük boyutlardadır.

NESNEYE YÖNELİK PROGRAMLAMA

Javascript. 1) Notepad++ aşağıdaki kodları yazıp deneme.html olarak kaydedelim. 2) Biraz önceki sayfa sadece html kodların içeriyordu.

Adım Adım Windows 2000 Server Kurulumu 11 Cuma, 08 Eylül :32 - Son Güncelleme Cumartesi, 12 Eylül :45

Programlama Nedir? Bir bilgisayar bilimcisi gibi düşünmek ve programlama ne demektir?

How to ASP Language. Elbistan Meslek Yüksek Okulu Bahar Yarıyılı. Öğr. Gör. Murat KEÇECĠOĞLU. 29 Eki. 1 Kas. 2013

5S7 OYUN YAZIYORUM GENEL BAKIŞ A. PROJE - YILDIZ TOPLAYAN ÇOCUK

İnternet Programcılığı Öğr. Gör. Serkan AKSU PHP de Dizi-Değişkenler, Nesneler. Dizi Oluşturma. Tek Boyutlu Diziler

Genel Programlama II

GOOGLE DRİVE KULLANARAK FORM OLUŞTURMA

Dizi elemanları yukarıdaki gibi tek tek tanımlanabileceği gibi matematiksel ifadelerdeki diziler gibi de tanımlanabilir.

VERİ TABANI NEDİR A. TABLO OLUŞTURMA

Internet Programming II. Elbistan Meslek Yüksek Okulu Bahar Yarıyılı

WEB TASARIM I. Öğr. Gör. M. Mutlu YAPICI. Ankara Üniversitesi Elmadağ Meslek Yüksekokulu

Okuyarak kelime öğrenmenin Yol Haritası

Internet Programming I. Hafta III. Elbistan Meslek Yüksek Okulu Güz Yarıyılı. Öğr. Gör. Murat KEÇECĠOĞLU

BİLGİSAYAR PROGRAMLAMA. Yrd. Doç. Dr. Beytullah EREN

Yrd. Doç. Dr. Caner ÖZCAN

if (ad == "Sabri") Console.WriteLine("Merhaba Sabri. Ne zamandır gözükmüyodun...");

CAMPUSIUM UZAKTAN EĞİTİM SİSTEMİ KULLANIM KILAVUZU

ASP.NET ile Bir Web Sitesi Oluşturma

BLM 112- Programlama Dilleri II. Hafta 5 İşaretçiler (Pointers)

PROGRAMLAMAYA GİRİŞ FONKSİYONLAR

C# Programlama Dili. İlk programımız Tür dönüşümü Yorum ekleme Operatörler

Pointer Kavramı. Veri Yapıları

BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜM BAŞKANLIĞI DERS TANITIM BİLGİLERİ

Spring Giriş Eğitimi

Teknik Doküman. Autodesk Revit Building te yeni ölçü tipleri yaratmak

Yrd. Doç. Dr. Caner ÖZCAN

BİLGİSAYAR BİLİMİ DERSİ (KUR 1) PYTHON PROGRAMLAMA DİLİ ÇALIŞMA KÂĞIDI - 1

ELN1001 BİLGİSAYAR PROGRAMLAMA I

Üst düzey dillerden biri ile yazılmış olan bir programı, makine diline çeviren programa derleyici denir. C++ da böyle bir derleyicidir.

DAO İLE SQL KOMUTLARI. Sql komutlarını artık veri tabanında kullanmaktan başka çaremiz yok arkadaşlar. Şimdi bu sql derslerimize başlayalım.

Python Programlama Dili

Bilgisayarda Programlama. Temel Kavramlar

MATRİKS VERİ TERMİNALİ GELİŞMİŞ ALARM

DİZİLER-KATARLAR ALGORİTMA VE PROGRAMLAMA II

Autofs. Hüseyin Kaya

Bir dizinin boyutları sabittir ve kullanılmadan önce belirlenmelidir. Dizi boyutunu belirlemek için başka bir değişkende kullanabilirsiniz.

Temel Bilgisayar Programlama

5.HAFTA. Sınıf ve Nesne Kavramı, Metot Oluşturma, Kurucu Metot, this Deyimi

Denetim Masası/Programlar/Windows özelliklerini Aç/Kapat

Şimdi başka bir problem üzerinde çalışalım.

Problem Yaklaşım Temelleri, Algoritma ve Akış Şeması

Göstericiler (Pointers)

C Programlama Dilininin Basit Yapıları

Kullanım Kılavuzu


Verimlilik İçin ETKİN BİLGİ YÖNETİMİ KENDİ FONKSİYONUMUZU YAZALIM

Hacettepe Robot Topluluğu

5. HAFTA KBT204 İNTERNET PROGRAMCILIĞI II. Öğr.Gör. Hakan YILMAZ.

BTP 207 İNTERNET PROGRAMCILIĞI I. Ders 9

1 NEDEN PROGRAMLAMA ÖĞRENMELIYIZ?

OYUN GELİŞTİRME AŞAMALARI-I

B03.10 Algoritmalari Uygulamak : Durum 3 (Yuvalı Kontrol Yapıları) Şimdi başka bir problem üzerinde çalışalım.

Arş.Gör.Muhammet Çağrı Gencer Bilgisayar Mühendisliği KTO Karatay Üniversitesi 2015

HSancak Nesne Tabanlı Programlama I Ders Notları

INPUTBOX KULLANIMI. Komut Düğmesine uygulanan algoritma örneği

YZM 2105 Nesneye Yönelik Programlama

Toplama işlemi için bir ikili operatör olan artı işareti aynı zamanda tekli operatör olarak da kullanılabilir.

UZAYLIYLA SOHBET. Kedi kuklasını silip bu kuklalardan birini seçin ve projenize başlayın.

ALGORİTMA VE PROGRAMLAMA II

Hızlı Başlangıç Kılavuzu

Bilişim Garaj Akademisi Nedir?

Özyineleme (Recursion)

SIMAN KULLANIM KILAVUZU

BBS515 Nesneye Yönelik Programlama. Ders 1 Zümra Kavafoğlu

PHP 1. Hafta 2.Sunum

ALGORİTMA VE PROGRAMLAMA I

HSancak Nesne Tabanlı Programlama I Ders Notları

BİL-142 Bilgisayar Programlama II

BM-209 Nesne Yönelimli Programlama. Yrd. Doç. Dr. İbrahim Alper Doğru Gazi Üniversitesi Teknoloji Fakültesi Bilgisayar Mühendisliği Bölümü

ALGORİTMA VE PROGRAMLAMA I

Dinamik Kodlama. [X] [X] Yeni Fonksiyon

Eğitsel Oyun Projesi Raporu. ÖĞRENEREK EĞLENİYORUM Berkay Bekaroğlu

1. HAFTA KBT204 İNTERNET PROGRAMCILIĞI II. Öğr.Gör. Hakan YILMAZ.

BÖLÜM 3 OPERAT A ÖRLER

JAVA DÖNGÜ DEYİMLERİ. For Döngüsü

k ise bir gerçek sayı olsun. Buna göre aşağıdaki işlemler Matlab da yapılabilir.

Ders 8: Metotlar. barisgokce.com

Bilgisayar Programcılığı Ön Lisans Programı WEB EDİTÖRÜ. Öğr. Gör. Rıza ALTUNAY

2-Hafta Temel İşlemler

C#(Sharp) Programlama Dili

Captain d e.

3. BELGE DENETİMİ. Bu bölümde belge denetimi için gerekli olan yazım, dil bilgisi ve dil ayarlarını öğreneceğiz.

Java JDK (Java Development Kit) Kurulumu:

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

Kurumsal Güvenlik ve Web Filtreleme

Transkript:

Lispi bu kadar güçlü kılanın ne olduğunu hiç merak ettiniz mi? Şimdi bunu kendiniz keşfedebilirsiniz- Üstelik bunu yapmak için bilgisayarınıza hiçbir şey yüklemenize gerek yok! A COMIC BOOK By Conrad Barski, M.D. LISPERATI.COM Bu belge İstanbul Bilgi Üniversitesi Bilgisayar Bilimleri Bölümü öğrencisi Seda Çelebican tarafından Türk diline çevrilmiştir. Belgenin Türk kültürüne uyarlanmasında ve genel editörlük işlemlerinde İstanbul Bilgi Üniversitesi emba Yazılım Geliştirme ekibinden Emre Sevinç emek harcamıdştır. Bu süreçte çok titiz eleştirileri, geri beslemeleri ile bize yardımcı olan Bilkent Bilgisayar Mühendisliği bölümü öğrencilerinden Hayrettin Gürkök'e ve Lisp konusunda yardımcı

olan Bülent Murtezaoğlu'na teşekkürü bir borç biliriz. Belgedeki hatalardan çevirmen ve editör sorumludur. Orjinal belgenin yazarı Dr. Conrad Barski hiçbir maddi hatadan ötürü sorumlu tutulamaz. Belgeyle ilgili tartışma için fazlamesai.net adresini kullanabilirsiniz. Lisp ile programlama yapmayı öğrenmiş herhangi biri size onun diğer tüm programlama dillerinden farklı olduğunu söyleyecektir. O, pek çok bakımdan şaşırtıcı derecede farklıdır- Bu çizgi roman size Lispin eşsiz tasarımının onu nasıl güçlü kıldığını gösterecek. Bu kılavuzda ufak tefek Lisp kodları vardır ve bu font ve renktedir... sadece bu kod parçacıklarını Lisp derleyicisinin komut satırına kopyalayın ve bu kılavuzun sonuna eriştiğinizde kendinize ait bir macera oyununuz olacak! Kullanabileceğiniz pek çok muhteşem Lisp derleyicisi vardır, ancak bu kılavuzla birlikte en kolay kullanabileceğiniz Franzın Allegro Common Lispidir.Bu çok güçlü ticari Lisp, Franz,Inc. tarafından nezaketle bir telnet ortamından erişilebilir hale getirildi, yani bilgisayarınıza hiçbir yazılım yüklemeden onu BURADAN kullanabilirsiniz. Sadece bağlantıya tıklayın ve tarayıcınız size ihtiyacınız olan her şeyi sunan bir telnet penceresi açacaktır!

(Kullanmayı sevdiğim bir diğer Lisp ise açık kaynak CLISPtir, eğer Lisp ile çok zaman geçirmeyi düşünüyorsanız bunu indirmeyi tercih edebilirsiniz.) Eğer Allegro Common Lisp kullanıyorsanız lütfen Lisp komut satırından şu satırı çalıştırın: (setf tpl:*print-length* nil)...sadece yazıyı tarayıcınızdan kopyalayın, sonra telnet penceresinde sağ tıklayıp Yapıştırı (Paste) seçin. Bu satırın üzerinde fazla durmayın- sadece Allegronun metin tabanlı macera oyunumuzun bastığı mesajları silmesini engelliyor.

Sözdizim ve Anlamlandırma Her bilgisayar dilinin sözdizim ve anlamlandırma'dan olusan bir kodu vardır. Programlama dilinin sözdizim'i, programın takip etmesi gereken en temel iskeleti oluşturur böylece derleyici programınızın içinde neyin ne, neyin fonksiyon neyin değişken, olduğunu anlar. Bir programın anlamlandırması biraz daha gelişigüzel olan kısmıdır, mesela mevcut değişik komutlar ve programın herhangi bir anında bakabileceğiniz değişkenler. Lisp'i özel kılan ilk şey başlıca programlama dilleri arasında en basit sözdizimine sahip olmasıdır. Kısaca, Lisp sözdizim'i der ki; Lisp derleyicisine girilen her metin listeler halinde düzenlenmeli, bunlar da listelerin listesi olarak ya da gereğince düzenlenir. Parantezler her listenin başını ve sonunu belirler: Ayrıca Lisp derleyicisi kodunuzu okurken iki kip kullanır: Kod Kipi ve Veri Kipi, listelerinize istediğiniz her şeyi koyabilirsiniz. Ancak derleyici kodunuzu okurken önce Kod Kipinden başlar- Kod Kipinde, listeleriniz "form" adı verilen özel listelerden olmalıdır:

Form, ilk sembolü derleyicinin anlayabileceği özel bir kelime olan liste olarak düşünülebilir; söz konusu ilk sembol genellikle bir fonksiyonun adı olur. Bu durumda derleyici diğer elemanları fonksiyona parametre olarak gönderir. Genellikle, siz veri kipine geçmesini söylemediğiniz sürece, bu parametrelerin de Kod Kipi'nde olduğunu varsayar. Oyun Dünyamız için Verileri Tanımlamak Formlar hakkında daha fazla bilgi edinmek için oyun dünyamızın verilerini oluşturacak formları yaratalım. Oynumuzda oyuncunun alıp kullanabileceği objeler olacak, öncelikle bu objeleri tanımlayalım: (setf *nesneler* '(viski-sisesi kova kurbaga zincir)) Şimdi bu satırı parçalara bölelim ve ne dediğine bakalım: Bir Lisp derleyicisi hep Kod Kipinde okumaya başlar ve bir form bekler, yani ilk sembol, setf, bir komut olmalıdır. Bu durumda komut, değişkene bir değer atamaktadır: Değişken *nesne*dir (Lispçiler global değişkenleri iki yıldız arasına yazmayı severler) ve onu eşitlediğimiz değer de dört nesneli listemiz.şimdi, listemiz veri tipinde olduğu için (derleyicinin viski-sisesi isimli bir fonksiyonu çağırmaya çalışmasını istemiyoruz yani) derleyiciyi listeyi okurken Veri Kipine döndürmemiz gerekiyor. Listenin önündeki kesme işareti derleyiciye dönmesini söyleyen komuttur:

Komutun neden setf olarak isimlendirildiğini merak ediyor olabilirsiniz. Açıkçası ben de pek emin değilim ama fark edeceksiniz ki Lispte pek çok komutun garip isimleri var, ne de olsa Lisp çok eski bir dil. Bu aslında yararlı bir durum, genel komutların Lisp sürümleri Lispe özel tüm zarif güçlerine sahiptir yani bu garip isimler Lispteki komutlarla diğer dillerdeki komutların karışmasını engeller. Mesela setf komutu bu klavuzda değinebileceğimizin ötesinde becerilere sahiptir. Şimdi dünyamızdaki bazı nesneleri tanımladık, bir adım daha ileri gidip dünyanın gerçek halini tanımlayalım. Dünyamızın neye benzediğine ilişkin resim: Bu basit oyunda sadece üç değişik mekan olacak: oturma odası ve çatı katı ile bahçesi olan bir ev. Bu küçük dünyayı anlatacak *harita* isimli yeni bir değişken tanımlayalım:

(setf *harita* '((oturma-odasi (büyücünün evindeki bir oturma odasindasiniz. kanepede horul horul uyuyan bir büyücü var.) (bati kapi bahce) (ustkat merdiven cati-kati)) (bahce (güzel bir bahcedesiniz. onünüzde bir kuyu var.) (dogu kapi oturma-odasi)) (cati-kati (terk edilmis evin cati katindasiniz. kösede dev bir kaynak makinasi var.) (altkat merdiven oturma-odasi)))) Bu harita bizim üç mekanımızla da ilgili önemli olan her şeyi içermektedir: mekana ait özel bir isim (yani ev, bahce ve cati-kati), oradan görülenlerle ilgili kısa bilgi (büyük listenin içinde kendine ait bir listede saklanmakta), ve o yerin içeri ve dışarı yollarıyla ilgili nereye ve nasıl yöntemleri. Bu tek değişkenin ne kadar bilgi zengini olduğuna ve sadece bilmemiz gerekenleri anlattığına dikkat edin Lispçiler küçük, kısa ve öz olan, fazlalık yapan her şeyi dışarda bırakan ve sadece bakarak anlaşılabilen kod parçacıkları yaratmayı severler. Artık bir haritamız ve çeşitli nesnelerimiz olduğuna göre bu nesnelerin haritada nerelerde olduğunu söyleyen bir değişken yaratmamız mantıklıdır: (setf *nesne-yerleri* '((viski-sisesi oturma-odasi) (kova oturma-odasi) (zincir bahce) (kurbaga bahce))) Burda her nesneyi bir yer ile ilişkilendirdik. Bu cins listeler Lispte tahmin edeeğiniz üzere ilişkilendirme listeleri olarak adlandırılır. Bir ilişkilendirme listesi kısaca bir listeler listesidir, bu iç listelerin her birinin ilk elemanı bir anahtar semboldür ve diğer bir takım verilerle ilişkilendirilmiştir. Aynı zamanda *harita* değişkenimiz de bir ilişkilendirme listesidir burdaki üç anahtar ise oturma-odasi, bahce ve catikati. Dünyamızı ve içindeki nesneleri tanımladığımıza göre geriye kalan tek şey oyuncunun nerede olduğunu tanımlamaktır: (setf *yer* 'oturma-odasi) Şimdi oyun komutları yapmaya başlayalım!

Oyun Dünyamızda Etrafa Bakınmak Sahip olmak isteyeceğimiz ilk komut bize bulunduğumuz yeri söyleyecek olan komuttur. Peki bir fonksiyonun dünyadaki bir yeri tanımlamak için neye ihtiyacı olabilir? Tanımlamasını istediğimiz yerin neresi olduğunu bilmek ister ve bir haritaya bakabilmek ve o haritada bu yeri bulabilmek ister. İşte tam olarak bunu yapan fonksiyonumuz: (defun yer-tarif-et (yer harita) (second (assoc yer harita))) Tahmin edebileceğiniz gibi defun kelimesi bir fonksiyon tanımladığımız anlamına geliyor. Fonksiyonun adı yer-tarifet ve iki parametre alır: bir yer ve bir harita. Bu değişkenlerin iki yıldız arasında olmamasından onların yerel olduklarını anlıyoruz yani global *yer* ve *harita* değişkenlerinden farklıdırlar. Lisp'teki fonksiyonların diğer programlama dillerindekilerden çok matematiksel fonksiyonlara benzediğine dikkatinizi çekmek isterim: Tıpkı matematikteki gibi bu fonksiyon da kullancıya okuması için bir şeyler basmaz ya da bir mesaj kutusu açmaz: Tek yaptığı tanımı içeren fonksiyonun sonucuna göre bir değer döndürmektir. Bulunduğumuz yerin oturma-odasi olduğunu düşünelim (ki gerçekten de öyle..)

Burası için bir tanım bulmak için öncelikle haritadan oturmaodasi'nı gösteren noktayı bulması gerekiyor. İşte bunu assoc komutu yapıyor ve bize oturma-odasi'nı tarif eden veriyi dönüyor. Sonra second komutu listedeki ikinci nesneyi yani oturma-odasi'nın tanımını siler (Eğer yarattığımız *harita* değişkenine bakarsanız, oturma-odasi'ni tanımlayan yazı parçacığı, oturma-odasi ile ilgili bütün veriyi toplayan listenin ikinci nesnesi olduğunu görürsünüz.) Şimdi Lisp prompt'umuzu kullanarak fonksiyonumuzu deneyelim- Kılavuzumuz boyunca olduğu gibi gene bu font ve renkte olan yazıları Lisp komut satırına yapıştırın: (yer-tarif-et 'oturma-odasi *harita*) ==> ( BÜYÜCÜNÜN EVINDEKI BIR OTURMA ODASINDASINIZ. KANEPEDE HORUL HORUL UYUYAN BIR BÜYÜCÜ VAR. Mükemmel! Tam istediğimiz gibi.. oturma-odasi'nin önüne koyduğumuz kesmeye dikkatinizi çekmek isterim, ne de olsa bu sembol yeri adlandıran veri (yani bunu Veri Kipi'nde okumak istiyoruz), ancak *harita* sembolünün önüne bir kesme koymadik, çünkü bu durumda isteğimiz derleyicinin

*harita* değişkeninin sakladığı verilere ulaşması (yani derleyicinin Kod Kipi'nde olmasını ve *harita* kelimesine sadece ham veri olarak bakmamasını istiyoruz.) Pratik Programlama Stili Belki yer-tarif-et fonksiyonumuzun pek çok değişik yönden bayağı kaba olduğunu fark ettiniz. Öncelikle nden yer ve harita değişkenlerini parametre olarak alıyoruz da, direkt olarak global değişkenleri okumuyoruz? Bunun sebebi Lispçilerin genellikle Pratik Programlama Stili'nde yazmayı sevmeleridir (daha açık olmak gerekirse bu- "prosedürel programlama" ya da- "yapısal programlama" ile tamamen alakasızdır..). Bu stilde amaç şu kuralları daima izleyen fonksiyonlar yazmaktır: 1. Sadece fonsiyona verilen ya da fonksiyon tarafından yaratılmış değişkenleri okur. (Yani hiç bir global değişken okunmaz.) 2. Asla atanmış bir değişkenin değeri değiştirilmez. (Yani değişkenleri arttırmak yada benzer saçmalıklar yok.) 3. Asla dış dünya ile etkileşime girmez, sonuç değerini döndürmek hariç. (Yani dosyalara yazma, kullanıcıya mesaj yazma yok.) Belki de bu katı kısıtlamalarla gerçekten işe yarayan bir şeyler yapan bir kod yazıp yazamayacağınızı merak ediyorsunuzdur... Kim bu kuralları izleme zahmetine katlanır ki? Çok önemli bir sebep: Bu stilde kod yazmak programınıza ilişkisel şeffaflık verir: Bu demek oluyor ki, verilen bir kod parçası aynı parametrelerle çağırıldığında, her zaman aynı değeri döner ve her ne zaman çağrılırsa çağrılsın hep aynı şeyi yapar- Bu programlama hatalarını azaltır ve ayrıca pek çok durumda programcının üretkenliğini arttırdığına inanılır. Elbette her zaman için fonksiyonel stilde olmayan fonksiyonlar ya da kullanıcı veya dış dünya ile iletişim kuramayacağınız durumlar olacaktır. Bu klavuzda bundan sonra karşılaşacağınız çoğu fonksiyon bu kuralları izlemeyecek. yer-tarif-et fonksiyonumuzla ilgili bir diğer poblem ise bize

o yerden başka yerlere doğru olan yolları söylememesi. Bu yolları bize tarif eden bir fonksiyon yazalım: (defun yol-tarif-et (yol) `(,(first yol) ile,(second yol) arasinda bir yol var.)) Pekala, bu fonksiyon bayağı garip görünüyor: Hatta bir fonksiyondan çok bir veri parçasını andırıyor. Önce deneyelim, yaptığını nasıl yaptığını sonra anlarız: (yol-tarif-et '(bati kapi bahce)) ==> (BATI ILE KAPI ARASINDA BIR YOL VAR.) Artık her şey açık: Bu fonksiyon yolu tarif eden bir liste alır (tıpkı *harita* değişkenimizin içinde olan gibi) ve ondan güzel bir cümle çıkarır. Şimdi fonksiyona tekrar bakarsak fonksiyonun yarattığı veriye çok benzediğini göreceksiniz: Kısaca yoldan ilk ve ikinci cisimleri kesip belirlenen cümleye çevirir. Bunu nasıl yapar? Ters-kesme kullanarak! Daha önce de derleyicimizi Kod Kipi'nden Veri Kipi'ne döndürmek için kesme kullandığımızı unutmayın- Terskesme kullanarak sadece dönmekle kalmaz ayrıca Kod Kipi'ne virgül ile geri de dönebiliriz: Bu- œters-kesme" tekniği Lisp'in muhteşem bir özelliği- bize yarattığı veri gibi gözüken kod yazmamıza izin veriyor. Bu çoğunlukla fonksiyonel stilde yazılan kodla olan bir şey: fonksiyonlarımızı ürettikleri veriye benzer şekilde yarattığımızda kodumuzu daha kolay anlaşılır yaparız ve aynı zamanda uzun ömürlü olmasını sağlar. Veri değişmediği sürece, fonksiyonlar veriyi sıkı bir şekilde takip ettiğinden, onların refaktörize edilmesi ya da değiştirilmesi muhtemelen gerekmeyecektir. Böyle bir fonkiyonu VB ya da C'de nasıl yazardınız bir düşünün: Büyük olasılıkla yolu parçalara bölerdiniz sonra da yazı parçacıklarını tekrar birbirine eklerdiniz- Yaratılan veriye hiç benzemeyen ve düşük ihtimalle uzun ömürlü olacak, daha rastgele bir süreç. Artık bir yol tanımlayabiliriz, ancak oynumuzdaki bir yer birden çok yola sahip olabilir. Haydi yollari-tarif-et isimli bir fonksiyon yaratalım: (defun yollari-tarif-et (yer harita) (apply #'append (mapcar #'yol-tarif-et (cddr (assoc yer harita))))) Bu fonksiyon, fonksiyonel programlama tekniğini kullanmakta: Yüksek Düzey Fonksiyonlar'ı kullanmak- Yani

apply ve mapcar fonksiyonları diğer fonksiyonları parametre olarak alıyor böylece onları kendileri çağırıyorlar- Bir fonksiyonu aktarmak için, fonksiyonun adından önce #' koymanız gerekir. cddr komutu listenin ilk iki elemanını kesip atar (böylece geriye sadece yol verisi kalır). mapcar kısaca başka bir fonksiyonu listedeki her nesneye uygular, temel olarak yaptığı bütün yolları yol-tarif-et fonksiyonu ile güzel açıklamalara dönüştürür. "apply #'append" ise sadece parantezleri temizler ve çok önemli değildir. Haydi bu yeni fonksiyonu deneyelim: (yollari-tarif-et 'oturma-odasi *harita*) ==> (BATI ILE KAPI ARASINDA BIR YOL VAR. USTKAT ILE MERDIVEN ARASINDA BIR YOL VAR.) Çok güzel! Hala tanımlamamız gereken bir şey var: bulunduğumuz yerin zemininde herhangi bir nesnenin olup olmadığı, varsa ne oldukları. Önce verilen yerde herhangi bir nesne var mı bunu söyleyen bir yardımcı fonksiyon yazalım: (defun is-at (nesne yer nesne-yeri) (eq (second (assoc nesne nesne-yeri)) yer))...eq fonksiyonu bize nesne-yeri listesindeki sembolün şu anki yer olup olmadığını söyler. Haydi bunu deneyelim: (is-at 'viski-sisesi 'oturma-odasi *nesne-yerleri*)

==> T t sembolü (ya da nil hariç bütün değerler) viski-sisesi'nin oturma-odasi'nda var olduğu anlamına gelir. Şimdi bu fonksiyonu yeri tanımlamak için kullanalım: (defun zemin-tarif-et (yer nesneler nesne-yeri) (apply #'append (mapcar (lambda (x) `(zeminde bir,x görüyorsunuz.)) (remove-if-not (lambda (x) (is-at x yer nesne-yeri)) nesneler)))) Bu fonksiyonda yeni bir kaç şey var: Öncelikle, isimsiz fonksiyonlara sahip (lambda bunun için sadece süslü bir isim). Bu ilk lambda formu, yardımcı bir fonksiyon tanımlamakla aynı (defun fasafiso (x) `(zeminde bir,x görüyorsunuz.)) ve sonra #'fasafiso'yu mapcar fonksiyonuna gönderir. remove-if-not fonksiyonu listeyi mapcar'a güzel cümleler kurmak üzere göndermeden önce içinden o an ki yerde olmayan bütün nesneleri çıkarır. Şimdi bu yeni fonksiyonu deneyelim: (zemin-tarif-et 'oturma-odasi *nesneler* *nesne-yerleri*) ==> (ZEMINDE BIR VISKI-SISESI GÖRÜYORSUNUZ. ZEMINDE BIR KOVA GÖRÜYORSUNUZ. ) Şimdi bütün bu tanımlayıcı fonksiyonları tek ve kolay bir BAK fonksiyonu ile bağlayabiliriz, bu fonksiyon global değişkenleri kullanarak (yani Fonksiyonel Stil'de olmadan) tanımlayıcı fonksiyonları besler ve her şeyi tanımlar: (defun bak () (append (yer-tarif-et *yer* *harita*) (yollari-tarif-et *yer* *harita*) (zemin-tarif-et *yer* *nesneler* *nesne-yerleri*)))

Haydi deneyelim: (bak) ==> ( BÜYÜCÜNÜN EVINDEKI BIR OTURMA ODASINDASINIZ. KANEPEDE HORUL HORUL UYUYAN BIR BÜYÜCÜ VAR. BATI ILE KAPI ARASINDA BIR YOL VAR. USTKAT ILE MERDIVEN ARASINDA BIR YOL VAR. ZEMINDE BIR VISKI-SISESI GÖRÜYORSUNUZ. ZEMINDE BIR KOVA GÖRÜYORSUNUZ. ) Çok şık! Oyun Dünyamızda Yürümek Artık dünyamızı görebildiğimize göre artık içinde yürüyebilmemizi sağlayacak kodu yazabiliriz. bir-yöndeyürü fonksiyonu (fonksiyonel stil'de değil) bir yön seçer ve o yönde yürümemizi sağlar: (defun bir-yönde-yürü (yön) (let ((sonraki (assoc yön (cddr (assoc *yer* *harita*))))) (cond (sonraki (setf *yer* (third sonraki)) (bak)) (t '(bu yönde gidemezsiniz.))))) let özel komutu bize sonraki yerel değişkenini yaratmamıza izin verir ve buna oyuncunun yürümek istediği yöne ait yol tanımını atarız- cddr ise sadece ilk elemanı listeden kesip alır. Eğer kullanıcı sahte bir yön yazarsa sonraki artık nil olur. cond komutu ise Lisp'te bir dizi if-then komutu gibidir: cond içindeki her satırın kontrol etmesi gereken bir değer ve yapması gereken bir görev vardır. Bu durumda, eğer sonraki yer nil değil ise oyuncunun yerini yol tanımındaki üçüncü elemana setf'leyecektir, ki bu da yeni yönü anlatan sembolü tutar, ve sonra kullanıcıya yeni yerin nasıl göründüğünü söyler. Eğer sonraki yer nilise o satırı gerçeklestiremeyip bir sonraki satıra gecer ve kullanıcıyı da uyarır. Haydi bunu deneyelim: (bir-yönde-yürü 'bati) ==> ( GÜZEL BIR BAHCEDESINIZ. ÖNÜNÜZDE BIR KUYU VAR. DOGU ILE KAPI ARASINDA BIR YOL VAR. ZEMINDE BIR KURBAGA GÖRÜYORSUNUZ. ZEMINDE BIR ZINCIR GÖRÜYORSUNUZ. ) Tanımlama fonksiyonlarımızı, oyuncumuza yazması kolay, bir bak komutu ile basitlestirmiştik. Benzer bir şekilde biryönde-yürü komutumuza da oyuncumuzun yazması gereken sinir bozucu işaretlemelerden arındıracak bir ayarlama yaparsak hoş olur. Ancak öğrendik ki, derleyici bir formu

Kod Kipi'nde okumaya başlarsa bütün parametrelerini de, bir kesme işareti aksini söylemedikçe Kod Kipi'nde okur. Derleyiciye bati'nin sadece bir parça veri olduğunu kesme işareti kullanmadan bir şekilde söyleyemez miyiz? TILSIM YARATMAK Şimdi Lisp'in inanılmaz güçlü bir özelliğini öğreneceğiz: TILSIM yaratmak! SPEL (ki biz tilsim olarak isimlendirdik), "Semantic Program Enhancement Logic" yani "Anlamlandırılmış Program Geliştirme Mantığı"nın kısaltmasıdır ve kendi bilgisayar dünyamızın kodunda yeni bir davranış stili yaratmamıza olanak sağlayarak Lisp dilini temel seviyede değiştirip ihtiyaçarımız doğrultusunda davranışlarını ayarlayabilmemizi sağlar- Lisp'in büyü gibi olan kısmı budur. TILSIM'ları kullanıma açmak için öncelikle Lisp derleyicimizde TILSIM'ları aktif hale getirmemiz gerekir (Bu satır için endişe etmeyin- ileri seviye Lispçiler buraya tıklamalı.) (defmacro deftilsim (&rest geriye-kalanlar) `(defmacro,@geriye-kalanlar)) Artık kullanıma açıldıklarına göre ilk tilsim'ımızı yaratalım, adı da yürü olsun: (deftilsim yürü (yön) `(bir-yönde-yürü ',yön)) Bu kodun yaptığı şey, derleyiciye yürü kelimesinin gerçekte yürü kelimesi olmadığını ve aslında onun bir-yönde-yürü demek olduğunu ve yön'ün önünde aslında -biz görmesek debir kesme işareti olduğunu söylemek. Esasen kodumuz derlenmeden önce onu başka bir şeye çevirecek olan bazı özel kodları programımız ve derleyici arasında bir yerlere sokuşturabiliriz.

Bu fonksiyonun daha önce yazdığımız yol-tarif-et koduna ne kadar çok benzediğine dikkat edin: Lisp'te birbirine neredeyse eş derecede benzeyen sadece kod ve veri değildir, kod ve derleyiciye özel komutlar (TILSIMlar) da benzeşir- Gayet tutarlı ve net bir tasarım! Haydi yeni tilsim'ımızı deneyelim: (yürü dogu) ==> ( BÜYÜCÜNÜN EVINDEKI BIR OTURMA ODASINDASINIZ. KANEPEDE HORUL HORUL UYUYAN BIR BÜYÜCÜ VAR. BATI ILE KAPI ARASINDA BIR YOL VAR. USTKAT ILE MERDIVEN ARASINDA BIR YOL VAR. ZEMINDE BIR VISKI-SISESI GÖRÜYORSUNUZ. ZEMINDE BIR KOVA GÖRÜYORSUNUZ. ) Çok daha iyi! Şimdi dünyamızda nesneleri kaldırmamızı saplayacak komutu yaratacağız: (defun nesneyi-al (nesne) (cond ((is-at nesne *yer* *nesne-yerleri*) (push (list nesne 'body) *nesneyerleri*) `(simdi bir,nesne tasiyorsunuz)) (t '(onu alamazsiniz.)))) Bu fonksiyon nesnenin gerçekten de o an ki yerimizin zemininde olup olmadığına bakar- eğer öyleyse yeni yeri (kullanıcının bedenini) listeye iter (itmek burda listeye yeni bir eleman eklemek manasındadır, bunu öyle yapar ki assoc komutu bunu görür ve bir önceki yeri gizler.) ve bize başarıp başaramadığını söyleyen bir cümle döndürür. Şimdi bu komutu daha kolay kullanmamızı sağlayacak bir başka TILSIM yaratalım:

(deftilsim al (nesne) `(nesneyi-al ',nesne)) Şimdi yeni TILSIMımızı deneyelim: (al viski-sisesi) ==> (SIMDI BIR VISKI-SISESI TASIYORSUNUZ) Şimdi bir kaç işe yarar komut daha ekleyelim- İlk önce taşıdığımız nesneleri listeleyen bir komut: (defun envanter () (remove-if-not (lambda (x) (is-at x 'body *nesneyerleri*)) *nesneler*)) Şimdiyse belli bir nesneye sahip olup olmadığımızı söyleyecek bir komut: (defun sahip (nesne) (member nesne (envanter))) Oynumuzda Özel Oyun Eylemleri Yaratma Artık yapmamız gereken tek bir şey kaldı ve sonra oynumuz tamamlanmış olacak: Oynumuza, oyuncunun yapmadan oyunu kazanamayacağı bazı özel oyun eylemlerini eklemek. İlk komut oyuncunun çatı katındaki zinciri kovaya kaynak yapmasını sağlayacak: (setf *zincir-kaynak-yapildi* nil) (defun kaynak-yap (ozne nesne) (cond ((and (eq *yer* 'cati-kati) (eq ozne 'zincir) (eq nesne 'kova) (not *zincir-kaynak-yapildi*)) (setf *zincir-kaynak-yapildi* 't) '(zincir güvenli sekilde kovaya kaynak yapildi.)) (t '(kaynak eylemini gerceklestiremem.)))) Şimdi ilk olarak, bu eylemi yapıp yapmadığımızı söylememize yarayan yeni bir global değişken yarattık. Sonra da kaynak yapmak için bütün şartların uygun olduğundan emin olmamızı ve kaynak yapmamızı sağlayan bir kaynak-yap fonksiyonu oluşturduk.

Haydi yeni komutumuzu deneyelim: (kaynak-yap 'zincir 'kova) ==> (KAYNAK EYLEMINI GERCEKLESTIREMEM.) Eyvaah.. bizim kovamız ya da zincirimiz yok, değil mi?...ve ortalıkta bir kaynak makinası da yok... eh peki.. Şimdi zincir ve kovayı kuyu'ya daldıracak bir komut yaratalım: (setf *kova-dolu* nil) (defun daldir (ozne nesne) (cond ((and (eq *yer* 'bahce) (eq ozne 'kova) (eq nesne 'kuyu) (sahip 'kova) *zincir-kaynak-yapildi*) (setf *kova-dolu* 't) '(kova simdi su dolu)) (t '(bu sekilde daldiramazsiniz.)))) Eğer dikkat ettiyseniz bu komut kaynak-yap komutuna fazlasıyla benzemektedir... Her iki komut da yer, özne ve nesneyi kontrol etmeye ihtiyaç duyuyor- Ancak onların benzerliklerini tek bir fonksiyona toplamamıza izin

vermeyecek kadar farklılıkları var.. Bu çok kötü......ancak bu Lisp olduğu için biz sadece fonksiyon yazmanın ötesine geçebilir ve tilsim yaratabiliriz! Haydi şu TILSIMı yaratalım: (deftilsim oyun-eylemi (komut ozn nsn mekan &rest geriye-kalanlar) `(deftilsim,komut (ozne nesne) `(cond ((and (eq *yer* ',',mekan) (eq ',ozne ',',ozn) (eq ',nesne ',',nsn) (sahip ',',ozn)),@',geriye-kalanlar) (t '(kusura bakma,',komut eylemini gerceklestiremem.))))) bu TILSIMın ne kadar gülünç bir şekilde karmaşık olduğunu fark ettiniz mi? - Daha çok garip kesme işaretleri, ters-kesme işaretleri, virgüller ve bir listeye sokabileceğiniz başka acaip sembollere sahip. Dahası bu bir başka TILSIM yaratabilen bir TILSIM! Daha ileri düzey Lisp programcıları bile bu kadar dev bir şey yaratabilmek için üzerinde düşünmeye ihtiyaç duyarlar (ve aslına bakarsanız onlar bu TILSIMı zerafetten yoksun bulup, bazı adımlar atarak onu daha iyi huylu yapmaya çalışacaklardır, ki biz bununla burda ilgilenmeyeceğiz..) Bu TILSIMın amacı sizlere bu TILSIMların ne kadar bilmiş ve becerikli olabileceklerini göstermekti. Hem çirkin olması, onu bir kere yazıp yüzlerce komut yaratmak için kullandıktan sonra çok da önemli değil. Şimdi yeni TILSIMımızı çirkin kaynak-yap komutunu değiştirmek için kullanalım:

(oyun-eylemi kaynak-yap zincir kova cati-kati (cond ((and (sahip 'kova) (setf *zincir-kaynak-yapildi* 't)) '(zincir güvenli sekilde kovaya kaynak yapildi.)) (t '(elinizde bir kova yok.)))) Bakın artık bu komutu anlamak ne kadar da kolaylaştı- oyuneylemi TILSIMı fazlalıklardan bizi kurtararak tam olarak söylemek istediğimizi yazmamıza izin veriyor- Sanki sadece oyun komutları için kendi bilgisayar dilimizi yarattık. TILSIMlar ile kendi sözde-dilinizi yaratmanıza Alana Özel Dil Programlama (DSLP - Domain Specific Language Programming) ismi verilir, bu en güçlü ve zarif programlama tekniklerinden biridir. (kaynak-yap zincir kova) ==> (ELINIZDE BIR ZINCIR YOK.) hala daha kaynak yapmak için uygun durumda değiliz ancak komutumuz işini yapıyor! Şimdi daldir komutunu da yeniden yazalım: (oyun-eylemi daldir kova kuyu bahce (cond (*zincir-kaynak-yapildi* (setf *kova-dolu* 't) '(kova simdi su dolu)) (t '(su seviyesi yetisemeyeceginiz kadar asagida.)))) kaynak-yap komutunun nesneye sahip olup olmadığımızı kontrol ettiğini ancak daldi komutunun o adımı atladığına dikkat edin -yeni oyun-eylemi TILSIMı kodu yazmayı ve anlamayı kolaylaştırıyor.

Ve son kodumuz, suyu büyücünün üzerine sallamak için: (oyun-eylemi salla kova büyücü oturma-odasi (cond ((not *kova-dolu*) '(kovada bir sey yok.)) ((sahip 'kurbaga) '(büyücü uyanir ve kurbagisini caldiginizi görür. o kadar cok hayal kirikligina ugrar ki sizi büyülü dünyadan men eder. kaybettiniz! oyun bitti.)) (t '(büyücü uyanir ve size hosgeldin der nazikce. size büyülü düsükkarbonatli kurabiye verir. kazandiniz. oyun bitti.))))

Tam anlamıyla bitmiş metin tabanlı bir macera oyunu yazdınız! Oyunun tam bir dökümü için BURAYA tıklayın. Lisp komut satırınıza tek bir adımda kopyalayıp yapıştırabileceğiniz kaynak kodu için BURAYA tıklayın. Bu klavuzu mümkün olduğu kadar basit tutmak için Lisp'in nasıl çalıştığıyla ilgili pek çok ayrıntı gizlenmiş ya da şöylece üzerinden geçilmiştir, o yüzden şimdi onlara bir bakalım...