|
|
Pascal Costanza'nın Çok Dik Başlı Lisp Rehberi
http://p-cos.net/lisp/guide.html
(v1.41, 9/8/2005, changelog.txt, eski sürüm
Korece çeviri: http://www.cesian.com/lisp.kr.html
Copyright © 2002, 2004, 2005 Pascal Costanza. Tüm hakları saklıdır.
Bu çalışmayı değiştirmeden ve bütünüyle kopyalama, yayınlama
ve saklama izni verilmiştir.
Bu belgeyi online başvuru kaynağı
olarak ya da yazdırarak kullanabilirsiniz. Tüm bağlantılar açık
URL şeklinde belirtilmiştir, yazdırıldıklarında da korunurlar.
Lütfen her türlü geribildiriminizi pc@p-cos.net
adresine yollayın.
Bölüm I: Ön bilgi
Hep bir oduncu olmak istemişimdir!
- Monty Python
1. Niçin bu tanıtımı yazıyorum?
Bu bölümü aslında Ağustos 2002'de yazmıştım. Aşağıda tasvir ettiğim
durum artık geçerli değil ama bu rehberin ruhunu korumak için zaman
kipini değiştirmemeye karar verdim.
Şu anki durumum şöyle. Son yedi yıldır, çoğunlukla Java programlama
diline uzantılar geliştirilen projelerde, Java programlama diliyle
çalışıyorum. Bundan önce, daha çok Wirth ailesinden diller
(çoğunlukla Modula-2 ve Oberon) kullanıyordum, yani başta Java'nın
sonraki dillere göre sahip olduğu bazı avantajlardan bir hayli memnundum.
Geçen sene içerisinde, Java'nın hala çok (aslında aşırı) sınırlı
bir programlama dili olduğunun farkına vardım ve alternatifler
aramaya başladım. Feyerabend projesiyle olan alakam nedeniyle
(
http://www.dreamsongs.com/Feyerabend/Feyerabend.html), Lisp, doğal
olarak alternatifler arasında göründü. (Richard Gabriel,
Feyerabend projesini başlatmıştı ve aynı zamanda 1980'lerin başında
Common Lisp standartlaştırmasını başlatan insanlardan biriydi.)
Bir sürü güzel programlama dili bulunmasına rağmen
(mesela, alfabetik sırada: gbeta, Objective CAML, Python, Ruby),
hemen Lisp'in, bir bakıma tüm dillerin anası olduğu izlenimini edindim.
Bu düşüncemin temel nedeni, Lisp'in kod ve veriye birörnek davranan tam
bir hesaplama teorisi içermesi. (Bu "sadece" Turing-tam
*
olmaktan daha
güçlüdür. Daha fazla bilgi için, aşağıdaki "Lisp'in Teknik Geçmişi"
bölümüne bakın.) Bunun uygulamadaki anlamı; Lisp'te hiçbir
(kavramsal) kısıtlama filan yoktur: eğer bir şeyi herhangi bir
dilde yapabiliyorsanız, Lisp'te de yapabilirsiniz. Dahası Lisp,
tüm türleri çalıştırma anında denetler, böylece hiçbir statik tür sistemi yolunuza çıkamaz.
Bu gözlemleri genelleyip şunu söyleyebilirsiniz: Lisp'in mantığı
iddia eder ki, ifade edebilme gücü, bir programlama dilinin yegane önemli
özelliğidir. O gücü kullanmak istediğinizde hiçbir şey yolunuza çıkmamalıdır.
Bir programlama dili dünya görüşünü programcıya dayatmamalıdır.
Programcı, dili kendi ihtiyaçlarına göre uyarlamalıdır, tersi olmamalıdır.
Bunun benim üzerimde büyük bir çekiciliği var ve bu yüzden Lisp'in
seçeceğim dil olmasına karar verdim. Yine de, Lisp'e daha ciddi olarak
bakmaya karar verdiğinizde bir kusur var: bu dil için Internet üzerinde,
benim ihtiyaçlarıma uyan, gerçekten çok iyi rehberler yok
- ya da en azından ben bulamadım. Elbette bazı rehberler bulunuyor
ama ya çok alt düzeydeler ve çok yeni başlayanlara programlamayı
öğretiyorlar, ya da çok akademikler ve sadece teorik olarak ilginç
konulara değiniyorlar. Benim görmeyi istediğim şey ise size
kavramları anlamanız için yeterli önbilgiyi sağlayan ve ardından
sizi olabildiğince çabuk ilerleten bir rehber. ("Uzman programcılar için Lisp"
gibi bir şey.)
Bir şey bulamadığım için, kendi kendime elimdekilerle çalışmak zorunda
kaldım. Şimdi, diğer insanlar için işleri kolaylaştırmak adına,
keşfettiklerimin bir özetini sunmak istiyorum.
2005 yılı itibari ile durumun dramatik olarak değiştiğini ve ilerleme
kaydettiğini belirtmektefayda var. Peter Seibel, 2005 Nisan tarihinde
yayımlanan bir Common Lisp kitabı yazdı. Kitabı aynı zamanda
ttp://www.gigamonkeys.com/book/
adresinde de bulabilirsiniz. Bir hayli pragmatik bir yaklaşım sergileyen
kitap "modern" kitleyi daha çok ilgilendirebilecek konular sunuyor:
spam filtreleri, MP3 fonksiyon kitaplıkları ve HTML üretme. Bunun
dışında Lisp büyümeye ve yaygınlaşmaya devam ediyor bu da
değişik kanallardan erişilebilen bilgi üzerinde çok olumlu
bir etkiye sahip.
Neden bu rehbere "çok dik başlı" deniyor? Lisp karmaşık bir dil, daha
doğrusu diller ailesi. Lisp için "tek mutlak rehber" olamaz. Benim
burada sunduklarım, ilk sırada görmeyi isteyeceğim şeyler. Diğer insanlar
muhtemelen farklı bir yaklaşımı tercih ederler. Herkes için her şeyi anlatan
bir rehber yazmak istemiyorum. Sadece benim gibi insanlara yararlı olabilecek
şeyleri sunmak istiyorum. En azından bende işe yarayan bu kaynak, belki diğer
insanlara da aynı şekilde uyabilir.
Özellikle bu, "Aptallar için 21 günde Common Lisp" gibi bir şey
değil. Gerçek "Common Lisp deneyimi" hissini yakalayabilmeniz için,
burada ya da başka bir yerde sunulan kaynakları birkaç kere yinelemeniz
gerekebilir. (...herhalde herhangi ciddi bir dile hükmetmek için 21 günden
çok daha fazlasına ihtiyacınız olduğunu vurgulamama gerek yok, değil mi? ;)
2. Genel tanıtım
Lisp'in uzun bir hikayesi var. 1950'lerde yaratıldı ve
onlarca yılda sürekli geliştirilip, iyileştirildi. Çeşitli
aşamalarda Lisp'in değişik lehçeleri oldu. Bu yüzden Lisp aslında
tek bir dil değil, bir diller ailesidir. (C, C++, Objective C, Java ve
C# gibi dilleri "C-benzeri" diller ailesinin üyeleri olarak düşünürseniz,
bunu anlayacaksınız.)
1980'lerde ve 1990'larda, iki ana lehçe kendilerini yaygın olarak
bulunan ve kullanılan lehçeler olarak kabul ettirdi: Common Lisp ve Scheme.
Scheme, 1970'lerde Gerald Jay Sussman ve Guy L. Steele tarafından,
nesne-yönelimli programlamayı anlamak ve Lisp'e dahil etmek için uğraşırlarken
yaratıldı. Scheme, kavramsal seviyede (nesnelerin bir genellemesi
olarak) "sözcüksel kuşatmalar"ı [1] ve
(fonksiyon çağrımı ve mesaj iletiminin genellemesi olarak)
"devam edişler"i [2]; teknik seviyede de
kuyruk çağrılarının ve kuyruk özyinelemelerinin [3]
aşırı optimizasyonunu ortaya çıkardı. Scheme'in iyi bir yanı da,
daha çok gerçek ve güzelliği (diğer bir deyişle; minimalite ve ortogonalite)
arayan akademisyenlere hitap eden özellikleri olan güzel bir mücevher olması.
Fakat, günlük programlamada ihtiyacınız olan bir çok pratik şey eksik
ve bu, kavramsal güzelliği berbat edebilir.
Yukarıda sözü geçen bazı terimlerin açıklamalarını
merak ediyorsanız, aşağıdaki bağlantılara bakın.
1970'lerin sonunda, Lisp'in birçok türü kullanımdaydı.
Common Lisp, bu abartılmış çeşitliliğe bir çare olarak
başlatıldı - o zaman var olan çeşitli Lisp'lerin faydalarının
birleştirilip, dezavantajlarının giderildiği, birleşmiş bir Lisp versiyonu.
Dahası, Common Lisp, ileri doğru atılmış büyük bir adımdı
çünkü Scheme'den öğrenilen dersleri de göz önünde bulundurmuştu.
(Sözcüksel kapsam Common Lisp'e girdi. "Devam edişler"
katılmadı çünkü pratik kullanım için çok karmaşık oluyorlardı.
Kuyruk özyinelemelerinin optimizasyonu standartlaşmaya ihtiyaç duymadı
çünkü bunu gerçekleştirme tekniği olarak kullanmak doğal bir ilerlemeydi.)
Böylece bunlar, bugün Lisp'i kullanmayı düşündüğünüzde
nelere bakmanız gerektiği hakkında size bir ipucu veriyor.
Eğer pratik "gerçek-dünya" uygulamaları yapmak istiyorsanız,
Common Lisp'i seçmelisiniz. Eğer daha çok akademik araştırma
yapmak ve mesela, "devam ediş" konusunda deney yapmak istiyorsanız,
Scheme'de de karar kılabilirsiniz. Her iki dil de bugün hala
kullanımda ve kendi kullanıcı toplulukları tarafından güçlü
olarak destekleniyorlar. (Lisp'in ayrıca Emacs Lisp ve Lush
gibi diğer çeşitleri de bulunuyor ama bunlar daha çok sınırlı,
alana özgü lehçeler.)
Ben bir çok nedenden dolayı Common Lisp kullanmaya karar verdim. Bazıları
bu rehber boyunca ortaya çıkacak. Scheme'de hoşuma gitmeyen,
onun işlerin nasıl yapılması gerektiği konusunda çok katı bir
"doğrucu" dil olması. Common Lisp çok daha serbest geliyor.
Gene de, Scheme hakkındaki yayınlar ve rehberler Common Lisp
için de uygulanabiliyor - örneğin, sözcüksel kuşatmanın ne olduğu -
bu yüzden ilerideki bölümlerde Scheme'e bazı başvurular ekledim.
(Özünde, benim iletim şu: Common Lisp ya da Scheme'i
seçmeniz önemli değil, bu sadece belirli ihtiyaçlarınıza
dayanır. Bu yüzden sadece içgüdüsel hislerinizin sizi
yönlendirmesine izin verin. Aslında iki dil de, hem araştırmada
hem de "gerçek dünya"da kullanılmak için yeterince esnekler.
Gene de yazımın büyük bölümü Common Lisp'le ilgili; bu yüzden
Scheme'i tercih ediyorsanız, bilgi kaynağı bulmak için başka
yerlere bakmalısınız. Yol göstericiler için aşağıdaki bağlantılar
bölümüne bakın. Bir seçeneğin hoşunuza gitmediğinin farkında
vardığınızda, bir de öbürünü deneyin.)
Belki de burası insanların Lisp ve Scheme isimlerini ne için
kullandıklarını anlatmak için iyi bir yer. Geniş anlamda
Lisp genellikle, Common Lisp, Scheme, (artık kullanılmayan) MacLisp,
InterLisp, Franz Lisp gibi daha eski lehçeler ve bir de Arc ve Goo gibi
yenilerini içeren diller ailesi için kullanılır. Dar anlamda,
Lisp şu an yalnız ve yalnız Common Lisp için kullanılıyor ve
bu da özellikle Scheme'i dışarıda bırakıyor! Lisp isminin ne kadar
geniş ve/veya dar kullanıldığı, kullanan kişiye ve bağlama göre
değişir. Bir ucunda genelde, geniş anlamda bile, Scheme'i dışarıda
bırakan, diğer ucunda da Dylan ve hatta Python'ı dahil eden
insanlardan oluşan geniş bir yelpaze var.
(Ben şahsen serbest olmayı ve belirli bir bağlamda önem
kazandığında açık olmayı tercih ediyorum.)
Bu kılavuzdan nasıl faydalanabileceğinize dair bir not: Bu belgeyi sırayla
okumayı doğal hale getirmeye çalıştım. Elbette bölümleri
atlamakta ve özellikle bölüm I ve II arasında gidip gelmekte
özgürsünüz. Fakat, ilerideki bazı bölümler biraz Lisp kodu
örnekleri görmüş olmanızı gerektirebilir. Bunun için bu yazıda
yeterli yön gösterici var.
3. Common Lisp'in "yöneticilere yönelik özetleri"
Common Lisp'in neler sunduğu hakkında tek sayfalık iyi bir
yazı
http://www.lisp.org/table/objects.htm adresinde bulunabilir.
Bu yazı, CLOS'in (the Common Lisp Object System -
Common Lisp'in bir parçası) nesne yönetim özelliklerine odaklanıyor
ama buna ek olarak Common Lisp'in fonksiyonel ve prosedürel
özellikleri için de iyi bir özet veriyor.
http://www.lispworks.com/products/lisp-overview.html'de bulunan
LispWorks'ün yazdığı The Common Lisp Language Overview bir başka iyi özet.
4. Bazı ilk engeller
Lisp'in geçmişi diğer programlama dillerininkinden farklıdır,
özellikle Algol ve C ailelerininkinden. Bu yüzden
Lisp topluluğu, değişik seviyelerde, farklı kavramlar ve
adlandırmalar geliştirmiştir. İşte karışıklığı önlemek için bazı açıklamalar.
-
Lisp'in dil tanımında yer alan fonksiyonlarından bazılarının komik görünen
isimleri var. Örneğin "car", bir listenin ilk öğesini almak
için, "cdr" de kalan öğeleri (gerisini) almak için kullanılır.
Listeler "cons" yardımıyla oluşturulabilir, "mapcar" liste üzerinde
ilerlemek için kullanılır, vb. Bilhassa Algol ve Wirth aileleri
dilleri genellikle Lisp tasarımcılarının niçin daha
"doğal" isimler kullanmadıklarını sorgularlar;
"first", "rest", "foreach" vb. gibi... En azından,
bu isimlerle karşılaştığımda benim verdiğim ilk tepkilerden
biri buydu (ve elbette bu tepkiyi veren sadece ben değilim).
Lütfen doğallık hakkındaki önyargılarınızı unutun
- Lisp'in, büyük ölçüde tarihsel sebeplerden dolayı,
sadece farklı bir kültürü var. Örneğin, sadece ve sadece
anadiliniz olduğu için hakkıyla İngilizce'nin de, sözgelimi,
Fransızca'ya göre daha doğal bir dil olduğunu iddia edebilirsiniz.
Lisp'in terimlerine alışmak, sadece bir ya da iki gün fiili kod
yazmayı alır ve sonra bunlar sorun olmaktan çıkar. Common Lisp
de alternatif isimler sunuyor, mesela "car" ve "cdr" için
"first" ve "rest", böylece seçme şansınız var. Gene de, geleneksel
isimler kullanan kodları okumaya hazırlıklı olmalısınız.
-
Aynı şey Lisp'in görünüşte aşırı parantez kullanımı
için geçerli. Bu sadece Lisp stili girintilemeyi destekleyen
iyi bir metin düzenleyicisi seçme meselesi, ardından parantezleri
çabucak unutursunuz. Lisp'te doğru sözdizim için çok nadiren
telaşlanacaksınız. Unutmayın ki sözdizimlerinden dolayı C benzeri dillerde
ve Pascal tabanlı dilinde, küme parantezleri ya da begin/end anahtar kelimeleri
(if, while, switch/case vb.) kontrol deyimlerinde yanlış kullanıldıklarında,
sorun yaratabilirler. Ancak, bu dillerde uzman bir programcıysanız,
tahminimce çok nadiren bu konularda sorun yaşarsınız. Aynısı Lisp
sözdizimi için de geçerli. Mesele sadece ona alışmakta.
-
Bazı insanlar hala, Lisp'in veri yapısı olarak sadece listeler
sunduğunu zannediyorlar. Bu düşünce onların çok eski Lisp
lehçelerini düşünmelerinden ve Lisp'in "List Processing"'in
(Liste İşleme) kısaltması olmasından kaynaklanıyor.
Aslında Common Lisp, diğer dillerde yararlı bulduğunuz her şeyi
sunuyor; struct'lar (C benzeri struct'lar), diziler,
hakiki çok boyutlu diziler, nesneler (Smalltalk and Java'daki gibi
alanlar ve metodlarla), karakter katarları... vb.
Benzer biçimde, bazı insanlar hala Lisp'in yorumlanan bir
dil olduğunu düşünüyorlar. Gerçek şu ki, Lisp'in tamamen yorumlayıcı
sistem olan gerçekleştirmesi çok az bulunuyor. Tüm ciddi gerçekleştirmeler,
doğrudan doğruya makina kodu üreten derleyiciler içeriyor. Böylece
Lisp genellikle derleme zamanı ve çalıştırma arasındaki farkı ayırt
eder. Bu fark örneğin makro programcılığında önem kazanıyor.
Hala, bu açıdan, C ve çoğu Pascal lehçeleri gibi sözde "derlenen diller"e
göre farklar var. Çoğu zaman, bir Lisp programını açıkça derleyip,
ardından çalıştırmazsınız. Bunun yerine, Lisp kodunu, yazıldıkça derleyen
(ÇN. on the fly) bir Lisp geliştirme ortamıyla etkileşime girersiniz.
Bu nedenle Lisp prensipte, "tam zamanında" (ÇN. just-in-time) derlenen diller türüne
yakındır. Lisp'in, örneğin (bir yere kadar aslında Lisp
ailesi üyesi olarak görülebilen) Smalltalk'un aynısı olan
bir etkileşimli yapısı vardır.
En önemli şey ise, Lisp'in çok verimli bir programlama dili
olmasıdır. Common Lisp üreticileri, mükemmel performansı sağlamak
için yıllardır çok sıkı çalışıyorlar. (Dikkat edin; JBuilder,
NetBeans, Eclipse gibi çağdaş Java ve benzeri IDE'ler, Lisp ve Smalltalk ile aynı düzeydeki
etkileşim yönüne muntazaman ilerliyor - yani açıkça Algol ve C benzeri
dillerin toplulukları tarafından dahi değerli görülüyor.)
Lisp'in başarım özelliklerinin Java ve C++ ile karşılaştırıldığı
yeni bir çalışma şu URL'de bulunabilir: Erann Gat, Lisp as an Alternative
to Java,
http://www.flownet.com/gat/papers/. (Bu çalışmadaki
Java programcılarının ne kadar deneyimli olduklarına dair
bir sorununuz varsa, daha fazla açıklama için lütfen
http://www.flownet.com/gat/papers/ljfaq.html adresine bakın.)
-
Lisp'in özelliklerinde çoğu kez kullanılan bir terim, "form"dur.
Bir form, Lisp sözdiziminin temel bir öğesidir. İşte bir örnek:
(format t "Merhaba, Dünya")
Bu, konsola "Merhaba, Dünya" yazdıran bir formdur.
("t" parametresi Common Lisp'te "doğruluk" için standart Boole mantık
değeridir [4] ve "format" fonksiyonu tarafından "standart
çıktı" için bir gösterge olarak yorumlanır.) Yani "form" terimi,
diğer programlama dillerindeki ifade ve deyimlerin
yerini tutar. (Bir Lisp fanatiği, Lisp'in
deyimleri [5] değil sadece ifadeleri
[6]
olduğunu ama bu ayrımın uygulamada önemli olmadığını iddia edecektir. Diğer
programlama dillerinde ifadeler ve deyimler arasındaki
sınır, sözde "ifade deyimleri"ne (değerleri dikkate alınmayan ifadeler)
izin verildiği için, belirsizdir. Aynısını Lisp'te de yapabilirsiniz ve
Lisp değeri olmayan (ya da "tanımlanmamış değerli") ifadeleri
bile tanımlar. Yani uygulamada, Lisp ve diğer diller aynı ayrımı
yapıyor ve benzer yollar kullanıyorlar, sadece farklı
"varsayılan davranışlar" gösteriyorlar.)
Lisp'te ayrıca "özel formlar" vardır. Bu terimi anlamanız için,
Lisp'te genellikle tüm formların, fonksiyonların uygulamaları
olduklarını bilmeniz gerekir. Yukarıdaki örnek,
"format" fonksiyonunun "t" ve "Merhaba, Dünya"
parametreli bir uygulamasıdır. Aşağıdaki örnek,
"foo" fonksiyonunun "bar" ve "goo" parametreli bir
uygulaması olurdu:
(foo bar goo)
Buna rağmen, Lisp'te fonksiyon uygulamaları belirtmeyen
formlar vardır. Bunlar ya makrolardır ya da "özel formlar"dır.
Özel formlar, sadece çok kısıtlı yerleşik işlemler kümesini
belirtir. (Bunlara Common Lisp gerçekleştirmesi tarafından
"özel olarak" davranılır. Dikkat edin, yerleşik fonksiyonlar
ve makrolar özel formlar değildir!) Formun bir fonksiyon formu,
makro formu ya da özel bir form olduğu, her zaman onun ilk
öğesinden anlaşılır. Çeşitli formlar arasındaki ayrımın bazı
teorik ve ayrıca pratik ilintisi var ama bunlar hakkında
önceden kaygılanmanıza gerek yok. Önemli hale geldiği zaman
farkı anlayacaksınız ve ardından bununla baş etmenin yollarını kolayca bulacaksınız.
-
Lisp topluluğunda, küçük-büyük diller konusunda büyük bir
çelişme vardı, bir dereceye kadar hala da var. Bu, diğer
topluluklardan insanlara şaşırtıcı gelebilir
(en azından benim için durum buydu). Peki, nedir sorun?
Lisp'in güzel bir özelliği de yerleşik fonksiyonları,
kullanıcı tanımlı fonksiyonlardan dikkat çekecek şekilde
ayırmaması. İşte iki örnek:
(car listem)
(cure listem)
car fonksiyonu Lisp'te önceden tanımlanmıştır,
cure için ise standart bir tanım yoktur bu yüzden
kullanıcı tanımlı bir fonksiyon olmalıdır. Önemli olan
nokta ise, farkı sözdizimden göremezsiniz. Bunu aşağıdaki,
Java programlama dilinden bir örnekle karşılaştıralım:
synchronized (lock) {
beginTransaction(...);
...
endTransaction(...);
}
Java'daki synchronized deyimi, belirli bir nesneyle
eşlemeli olarak kod öbekleri yazmanızı sağlayan,
yerleşik bir özelliktir. Bu örnekteki karşılıklı
işlem yapan (transaction) metodlar da (tahminen)
bu karşılıklı işlem kurallarını uygulayan kod öbekleri
tanımlıyorlar ama bunun Java programlama dilinin yerleşik
bir özelliği olmadığını anında anlayabilirsiniz.
(Evet, Lisp öbek-yönelimli (block-oriented) deyimler - pardon - formlar sunuyor;
ve evet, Lisp'in yerleşik özelliklerine benzeyen kendi
öbek-yönelimli formlarınızı yazmanız da mümkün.)
Şimdi, küçük-büyük dil meselesini anlamak için bu farkı hesaba katmalısnız.
Peki Java ya da benzer bir programlama dilini standartlaştırma
ne demektir? İlk önce dili standartlaştırmanız lazım ve
ayrıca kütüphanelerin bazılarını da standartlaştırmanız
lazım. Yukarıda belirtildiği gibi, bu tip dillerde yerleşik
özellikler ile kütüphaneler arasında gözle görülür bir fark var,
bu yüzden açıkça bunlar iki farklı iş.
Lisp dünyasında böyle değil. Çünkü yerleşik ve
kütüphane özellikleri arasında gözle görülür bir fark yok,
kütüphanelerin standartlaştırılması zorunlu olarak
dil standartlaştırmasının bir parçası haline geliyor
(ve bir anlamda tersi de geçerli).
Dolayısıyla küçük-büyük diller meselesi,
(Algol ve C benzeri terimlerle) küçük-büyük kütüphaneler
meselesine indirgeniyor - ve gerçekten de bu konuda söylenebilecek
başka bir şey yok!
Böylece bundan şu sonuç çıkıyor: Scheme, sadece çok küçük bir
standart kütüphane sunduğu için küçük bir dildir oysa
Common Lisp bir sürü yararlı ve standart özellikler
sunduğu için büyük bir dildir. Yine de, her iki dilin de en
temeline bakarsanız, büyüklük bakımından aşağı yukarı eşitler. (Dahası,
eğer "ciddi" Scheme gerçekleştirmelerine bakarsanız onlar da,
standartlaştırılmış olmasalar da, zengin özellikli kütüphaneler sunuyorlar.)
Ancak küçük-büyük diller meselesiyle alakalı olmayan,
kavramsal farklar var. Yani Scheme ya da Common Lisp arasında
seçim yapmak sadece dil büyüklüğü meselesi değildir.
-
Örneğin, bazen Scheme'in bir "Lisp-1" ve Common Lisp'in de
bir "Lisp-2" - ya da Scheme'in tek hücreli, Common Lisp'in
ise çok hücreli bir sistem olduğunu görürsünüz. Burada
bahsedilen şey bir elde değişkenlerin değerleri, diğer elde
de fonksiyon tanımlarının Scheme'de aynı yolla, Common Lisp'te
ise farklı yollarla saklandığıdır. Bu aslında uygulama yönünden
o kadar da önemli değil çünkü besbelli iki dilde de gerçek
programlar yazabilirsiniz. İkisi de Lisp-1 ya da Lisp-2 olmanın
sonuçlarıyla baş etmek için yollar sunuyorlar. Bunu, onunla gerçekten
karşılaşıncaya kadar rahatlıkla yoksayabilirsiniz ve yine,
bununla baş etmenin yollarını kolayca bulacaksınız.
(Bir "Lisp-1" uygulaması belli bir programlama tarzını daha
uygun kılıyor oysa bir "Lisp-2" uygulaması makro programlamayı
daha az hata eğilimli yapıyor ve nesne yönetimli özellikleri
daha uygun kılıyor. Tam ayrıntılar biraz tehlikeli. Teknik
çıkarımları daha fazla öğrenmek isterseniz, bunları
aşağıdaki çalışmada ayrıntılı olarak görebilirsiniz.
5. Lisp'in Tarihi
Lisp'in, Common Lisp ve Scheme'i de içeren, tüm geçmişinin kapsamlı
olarak anlatıldığı çok iyi yazılmış iki çalışma dikkate değerdir.
Hatta bazı devrelerde, bu iki çalışma adeta polisiye roman gibi
okunuyorlar - tavsiye edilir!
İkinci çalışma Lisp için oldukça eksiksiz bir kaynakça da içeriyor.
(Lütfen bunları Herbert Stoyan'ın Lisp'in geçmişi
hakkındaki diğer çalışmaları ile karıştırmayın.
Bana göre hem okuması zor hem de tuhaf sonuçlar
çıkarmanıza yol açan yazılardı.)
6. Lisp'in teknik geçmişi
Önceden belirttiğim gibi, Lisp koda ve veriye birörnek
olarak davranarak, eksiksiz bir hesaplama teorisi
içeriyor - ve bu Lisp'i güçlü kılan ana özelliklerden
biri. Bunun tam olarak ne anlama geldiği hakkında iyi bir
açıklama verebilecek iki kaynak öneriyorum.
(Bunlar "meta-döngüsel yorumlayıcılar" (meta-circular interpreters)
kavramıyla alakalılar - bu terim sizi korkutmasın,
göründüğü kadar karmaşık değil.) Şahsi fikrim, Lisp'in
gücünü gerçekten değerlendirebilmek için, en azından birincisini okuyun.
...ve bu arada, bu makale, Lisp'teki temel ("ilkel")
formlar hakkında iyi de bir açıklama veriyor.
"The Roots of Lisp"i sevdiyseniz ve meta-döngüsel
yorumlayıcılar hakkında daha çok şey bilmek istiyorsanız,
aşağıdaki çalışmada derin bir tartışma okuyup, bunlarla
neler yapabileceğinizi görebilirsiniz. Bunun yanında
sözcüksel kuşatma, dinamik bağlama ve benzer şeyler
hakkında yararlı bilgiler edineceksiniz.
(Bu çalışma arkadan başka bir çalışma geleceğini ima
ediyor ama böyle bir şey henüz ne yazıldı ne de yayınlandı.
O yüzden boşuna aramayın: alıştırma olarak açık kalan noktaları
tamamlamaya çalışın. ;)
7. Mevcut gerçekleştirmeler
Common Lisp gerçekleştirmelerinin bir listesini
http://lisp.tech.coop/Implementation
adresinde bulabilirsiniz. Bunlardan sadece bazılarını çok yakından
inceledim. Çoğu Lisp programcısı Lisp geliştirme ortamı olarak Emacs veya
XEmacs'i tercih ediyor ama ben daha çağdaş IDE'leri tercih ediyorum,
bu elbette benim arama alanımı kısıtladı. (Tartışmaya gerek yok,
bu mantıksız ve tamamen öznel zevk meselesi. Emacs editörünü kullanarak
bir IDE kurmaya hevesliyseniz, http://common-lisp.net/project/slime/
adresindeki SLIME'ı inceleyin. Ayrıca Peter Seibel
http://www.gigamonkeys.com/lispbox/
adresinde hazır yüklü Emacs tabanlı geliştirme ortamı olan Lispbox'ı sağlıyor.)
Apple Macintosh (Mac OS X) için özel öneri: Macintosh için LispWorks,
ücretsiz olarak indirilebilecek Personal Edition'ı ile,
mükemmel bir IDE. Macintosh Common Lisp de çok iyi bir IDE
ama LispWorks kadar Mac OS X'le uyumlu değil. Digitool'dakiler MCL'i
30 gün boyunca denemenize izin veriyorlar. CLISP, ECL, OpenMCL ve
SBCL, Mac OS X için bulunuyorlar ama IDEden yoksunlar, ki bu benim için
çok önemli. Franz, Inc. gelecekte Mac OS X için Allegro Common Lisp ile
bir IDE sunacak fakat kesin bir planları yok, o yüzden nefesinizi tutmayın.
Ben düzenli olarak hem Macintosh için LispWorks hem de
Macintosh Common Lisp kullanıyorum. Yine de, bu bir ürün
tavsiyesi değil - lütfen kendi gereksinimlerinizi kendiniz belirleyin!
Bölüm II: Eklektik bir kendi kendine öğrenme rehberi
HİÇKİMSE İspanyol Engizisyonu'nu beklemiyor! Bizim ana silahımız sürprizdir...sürpriz ve korku...korku ve sürpriz... Bizim iki silahımız korku ve sürprizdir...ve zalim verimlilik... Bizim *üç* silahımız korku, sürpriz ve zalim verimliliktir...ve Papa'ya olan neredeyse bağnaz bağlılığımızdır... Bizim *dört*...hayır...Silahlarımızın *en üstünde*... Cephanemizin en üstünde...korku, sürpriz gibi unsurlar var....Tekrar meydana çıkacağım....
- Monty Python
Yazımın bu bölümünde daha çok, Common Lisp'in çeşitli yönlerini
tanımanıza yardımcı olabilecek ipuçları ve kaynaklar veriyorum.
(Yani, daha çok standart kütüphanelerinden bahsediyorum.)
8. Başvuru kaynakları
Günlük programlamada genellikle fonksiyon tanımlarına,
sözdizim açıklamalarına... vb. şeylere bakmak için başvuru
kaynağına ihtiyaç duyarsınız. Bazı insanlar kitapları
tercih eder ve bazıları da online kaynakları.
Geçerli olan Common Lisp standardı, 1995'te çıkan ve
Common Lisp için en güvenilir kaynak olan
ANSI standardı olarak belirtilir. Fakat, okuması zordur
çünkü esasen sadece özellikleri belirtir, mesela temel mantığı belirtmez.
1990'ların başında Guy L. Steele, Common Lisp standartlaştırması
için bir rapor olan ve ANSI Common Lisp'e benzeyen
"Common Lisp the Language" kitabının ikinci sürümünü düzenledi.
(Bu sürüm 1980'lerdeki ilk sürümün üzerine geldi ve
genellikle CLtL2 olarak anılıyor. İlk sürüm -sadece CLtL-
artık kullanılmamalı.) CLtL2, ANSI Common Lisp'teki
bazı özelliklerden mahrum olmasına rağmen
-ayrıca bazı küçük farklar da var- genellikle başlangıç için
önerilebilir çünkü salt spesifikasyon yerine iyi tanımlamalar da
sunuyor. Bu, kaynağı anlamanızı bir hayli kolaylaştırıyor.
Yine de, birtakım tanımların tam ayrıntılarını bulmanız için,
ANSI özelliklerini elde bulundurmanız da önerilir.
Dahası ANSI belgesi, çok yararlı bir terimler sözlüğü içerir.
Neyse ki hem ANSI Common Lisp hem de CLtL2 kitapları HTML
(ve PDF/PS) belgesi biçiminde online bulunuyor ve
hatta bilgisayarınızda kullanmak üzere indirilebiliyor
(HTML sürümleri dahil). İşte bağlantılar:
Eğer basılı kaynak tercih ediyorsanız, ulaşmak için
biraz gayret sarfetmeniz gerekiyor. CLtL2 baskısı kalmadı
gibi ama Ebay'den kullanılmış bir kopyasını bulmayı
deneyebilirsiniz. Ayrıca Amazon gibi bazı (online)
kitapçılarda da hala mevcut.
http://www.bh.com/digitalpress/
adresindeki yayımcı sitesinden satın almayı da deneyebilirsiniz.
ANSI belgesi http://global.ihs.com/
adresinde mevcut fakat 1000'den fazla sayfadan oluştuğu için kullanışlı
ve/veya yararlı olduğunu tahmin etmiyorum. Dahası, 400$ civarı
fiyatıyla gerçekten pahalı.
Paul Graham'ın "ANSI Common Lisp"i (alta bakın) iyi bir
kitap ama başvurma amacı için yararlı bulmuyorum. Genellikle
ben basılı spesifikasyonları tercih ederim (Java dili spesifikasyonu gibi)
ama Common Lisp olayında elektronik sürümler de iyi.
9. En temeller
Paul Graham'ın yazdığı, "ANSI Common Lisp" adında bir
ANSI Common Lisp kitabı var. İyi bir parça ve şansımız
var ki yazar ilk iki bölümü web sayfasına koymuş.
Özellikle ikinci bölümü önerebilirim çünkü
çabucak Common Lisp'te programlamanın ne olduğu hakkında
uygulamalı deneyimler sunuyor.
Tarzını sevdiyseniz, o sayfadaki bağlantıları takip
ederek kitabı satın almayı düşünebilirsiniz.
Yeni başlayanlar için bir başka harika kaynak da Peter Seibel'in
"Practical Common Lisp" isimli kitabıdır, hem normal kitap olarak
hem http://www.gigamonkeys.com/book/
adresinde e-kitap olarak mevcuttur.
Sonrasında aradığınız çoğu bilgiyi CLtL2 ve/veya ANSI
spesifikasyonunda bulmak oldukça kolay olacaktır. Naçiz
fikrime göre elde etmesi biraz zor olan bazı bilgiler için aşağıya bakın.
Bölüm II'nin kalan kesimlerini tamamen anlayabilmeniz için,
şimdiye kadar "The Roots of Lisp" (
http://www.paulgraham.com/rootsoflisp.html) ya da
"ANSI Common Lisp Chapter 2"yi (
http://www.paulgraham.com/lib/paulgraham/acl2.txt) okumuş olmanız veya
başka yollarla Lisp koduyla en azından karşılaşmış olmanız gerekir.
10. Daha ileri temeller
Er ya da geç, daha küçük sorunlar içeren aşağıdaki
sorunlarla ilgilenmeniz gerekecek.
-
Common Lisp değişik kombinasyonlarda, opsiyonel argümanlarla,
"rest" argümanlarıyla ve varsayılan argümanlarla çalışan
fonksiyonlar tanımlama imkanlarını sunuyor.
Bunların nasıl tanımlanacağıyla ilgili tam bir
spesifikasyon CLtL2 bölüm 5.2.2'de ("Lambda Expressions")
ve ANSI spesifikasyonu bölüm 3.4'te ("Lambda Lists"),
özellikle de bölüm 3.4.1'de ("Ordinary Lambda Lists") bulunabilir.
(Lambda ifadeleri isimsiz fonksiyonlardır. İsimli fonksiyonlar,
diğer programlama dillerindeki yordamlara,
fonksiyonlara ve/veya metodlara benzerler.
Lisp'teki isimsiz fonksiyonlar Smalltalk'taki
öbeklere veya, bir dereceye kadar, Java'daki anonim
iç sınıflara benzerler. Açıklamalar için CLtL2
bölüm 5.2 ("Functions") ve alt bölümlerine bakın.)
-
Common Lisp'te standart çıktı, genellikle
format fonksiyonu aracılığı ile gerçekleştirilir.
Öz olarak C'deki printf'e benzerdir (yine de printf hakkında
kapsamlı bilgim olmadığını itiraf etmeliyim!). Format hakkında,
hiçbir çalışmada iyi bir genel tartışma bulamadım, bu yüzden
temel olarak CLtL2'deki ilgili maddeyi okumanız gerekli.
CLtL2'da format, bölüm 22.3.3'te
("Formatted Output to Character Streams") anlatılıyor.
ANSI spesifikasyonu bunu bölüm 22.3'te ("Formatted Output") kapsıyor.
-
Karakter katarları Common Lisp'te şu nedenlerle
biraz karmaşıktır. Common Lisp, Unicode'un çıkışından önce
standartlaştırılmıştır - fakat, ASCII veya başka sınırlı
karakter kümelerinin yeterli olmayacağı zaten belliydi. Bu yüzden
Common Lisp standardı karakter katarlarıyla ilgilenmek için,
bazı sorunları somut gerçekleştirmelere bırakan, genel yöntemler belirtir.
Genellikle bu bir problem olmamalı ama diğer programlama
dilleriyle yazılan uygulamalarla etkileşime geçmek isterken problem
olabilir. Allegro Common Lisp, CLISP ve LispWorks, Unicode desteği
sunuyor, diğer gerçekleştirmeler, bildiğim kadarıyla, (henüz) sunmuyor.
(Ancak bu bakımdan da durum çok hızlı değişiyor o yüzden belli bir Lisp
gerçekleştirmesinin durumunu yakından takip edin.
Elbette kendi kendinize de Unicode desteği gerçekleştirebilirsiniz -
Lisp bu amaçlar için yeterince esnektir. ;-)
Karakter katarları desteği ile ilgili daha fazla detaya
ulaşmak isterseniz, seçtiğiniz Common Lisp gerçekleştirmesiyle
sunulan dökümantasyonla bağıntılı CLtL2 ve ANSI spesifikasyonuna başvurun.
-
Dosya isimlerinin işlenmesi ortamdan ortama
farklılık gösterir. Yine Common Lisp, somut işletim sistemi
tarafından gerektiğinde, gerçekleştiricilerin boşlukları
doldurmalarına imkan veren bu tür "framework"leri
standartlaştırmıştır. Yani ayrıntılı bilgi edinmek için
yine CLtL2, ANSI spesifikasyonu ve Common Lisp gerçekleştirmenizin
dökümantasyonuna başvurmanız lazım. CL-FAD dosyalarla uğraşırken
taşınabilir (portable) kod yazmanıza yardımcı olan bir fonksiyon
kitaplığıdır. Detaylar için http://www.weitz.de/cl-fad/.
11. Makrolar
Common Lisp'in makro özelliği bu dilin en ilginç
yanlarından biridir - salt fonksiyonlar yerine,
kendi programlama dili yapılarınızı yazmanız için çok güçlü bir imkandır.
Makrolar, güçlü olmaları ve anlaşılmaları görünüşte
zor olduğu için, genellikle ileri seviye bir konu
olarak görülürler. Halbuki, ben bunları kavramsal
olarak epey basit ve yazması kolay bulmuştum.
Makrolar hakkında çok iyi bir tanımlama ve
bunların nasıl kullanılacağı, Paul Graham'ın
"On Lisp" kitabında bulunabilir.
Bunun baskısı tükenmiştir ama aşağıdaki URL'den ücretsiz indirilebilir.
Size benden bazı uyarılar ve notlar.
-
Common Lisp'teki makrolar, C'deki makrolar gibi değildir!
Anladığım kadarıyla, C'deki makrolar karakter katarlarını işlerler
ve işlettikleri programın yapısıyla ilgili hiçbir şey bilmezler.
Aksine, Common Lisp'teki makrolar, programların tam yapısında
çalışırlar. Bu mümkün, yine, çünkü Lisp'te kod ve veri birörnek
olarak işlenir. Yani bir program, bir formlar listesidir ve, tabii ki,
makrolar herhangi diğer bir liste gibi formlar listesini de işleyebilirler.
Eğer "makro" terimine içgüdüsel tepkiniz sizi vazgeçiriyorsa lütfen
iki kere düşünün - bu sadece diğer, daha gelişmiş, programlama
dilleriyle bağlantılı olarak oluşmuş önyargılardan kaynaklanıyor olabilir. ;-)
(Bundan sonra C makrolarıyla ilgili herhangi birşey söylemeyeceğimden, "makro" terimini sadece Lisp makroları için kullanacağım.)
-
Makrolar, bağımsız değişken olarak kod kabul eden ve karşılığında
yeni kod üreten fonksiyonlar olarak anlaşılabilirler. Bir makronun
bir uygulaması derleme zamanında bulunduğunda, ilgili form makroya
geçirilir ve sonuç bu formun yerine geçer. Derleme daha sonra yeni
formla devam eder. (Bu işleme "makro açılımı" denir.)
Şimdi "cure"u, car ile aynı olacak şekilde tanımlayan bir makro
tanımlayalım:
(defmacro cure (argument)
(list 'car argument))
Artık gördüğümüz her (cure a), derleme zamanında (car a)'ya dönüştürülür
- makronun sonucu, makro uygulaması yerine asıl kodun kullanılmasını
tanımlar.
(Not: Bu örnek sadece gösterme amaçlıdır.
Makroların kullanımı için iyi bir örnek değil:
"cure" bir fonksiyon olarak daha iyi tanımlanırdı.)
Burda görebileceğiniz, makroların Turing-tam
olduğu gerçeğidir. Common Lisp'in tüm gücü, derleme
zamanında makrolar içinde yeni kod üretmek için
kullanılabilir. Makrolar, sonuçlarını belirlemek için,
diğer makro açılımlarını ve fonksiyon uygulamalarını
içerebilirler ve, elbette, yineleme ve/veya özyineleme,
koşullu ifadeler, vb. dahi kullanabilirler. Oluşan kod
dahi makroların daha fazla uygulamalarını içerebilir,
bu oluşan kod tamamen fonksiyon uygulamalarından
oluşuncaya dek tekrar eden "makro açılımına" yol açar.
Yani, uygulamada, Common Lisp'teki makrolar, örneğin,
C++'ta kullanılan şablon meta-programlama
ile aynı amaç için kullanılabilir. Özellikle,
Üretken Programlama için kullanılabilirler!
(Üretken Programlama esasında, derleyicileri genel amaçlı
programlama dilleri için kod üreten, alana özgü dillerin
tanımı ile ilgilenir.)
-
Makrolar genellikle "backquote" (ÇN. ters tırnak) sözdizimi
ile bağlantılı olarak ortaya çıkarlar. Ben makroları bu
şekilde tanıtmanın, anlamayı gereksiz yere zorlaştırdığına
inanıyorum. Aslında makroların Turing-tamlığı konusundaki
bir önceki notu anladığınız zaman, kavramsal seviyede,
aklınızda makroların ne olduğu hakkında tam bir fikre sahip olursunuz.
Yine de makrolar ve backquote sözdiziminin kombinasyonu uygulamada
bazı değerli, sinerjik etkiler sağlayabilir.
Aşağıda backquote sözdizimini tanıtacağım ve daha sonra da
makrolarla nasıl birleştiğini göstereceğim.
Yukarıda bahsedildiği gibi, Lisp'teki formların çoğu
fonksiyon uygulamalarıdır. Yani (car mylist),
listenin ilk öğesini çekip mylist'in belirttiği
listeye koyar. Bazen bir formu çalıştırmak
istemeyebilirsiniz (onun bir fonksiyon uygulaması
olarak yorumlanmasını istemeyebilirsiniz). Mesela
(car (a b c))'de, (a b c) varsayılan olarak
üç öğeli bir liste olarak görülmez, a isminde, b ve c
parametreli bir fonksiyon olarak görülür. (a b c)'nin
değerlendirilmesini önlemek için "quote" özel formunu
kullanmanız gerekir; şöyle: (car (quote (a b c))).
Şimdi, bu ifadenin tamamının değerlendirmesi "a"yı verir
((a b c) listesinin ilk öğesi). Dikkat edin,
(quote ...) bir fonksiyon uygulaması değil,
özel bir formdur (Lisp'in yerleşik bir özelliği, yukarıya bakın).
"quote" Lisp'te çok sık kullanıldığından, quote sözdizimini
kullanımı şu şekilde kısaltılabilir: (car '(a b c))
aynen (car (quote (a b c))) anlamına gelir.
Bu arada quote, bir değişkenin değerlendirilmesini önlemek
için de kullanılabilir. Lisp'te değişkenler
(diğer programlama dillerinde olduğu gibi) sadece
isimlerdir, yani eğer, örneğin, (car a)
yazarsanız, "a" değişkeninin belirttiği listenin
ilk öğesi alınır. Değişkenlerin değerlendirilmesini
önlemek için, tahmin edebileceğiniz gibi, (quote a)
ya da kısaca 'a yazabilirsiniz.
Şimdi bazen değişik ifade ve/veya değişkeni değerlendirip,
bir listede birleştirerek listeler yaratmak isteyebilirsiniz.
Bunu Lisp'te yapmanın en basit yolu şöyledir: (list a (car b) c);
a, (car b) ve c'yi değerlendirir,
sonra da sonuçları tek bir listede birleştirir.
Bazen sadece bazı "liste" özel formu için parametrelerin
değerlendirilmesi gerekir. Bu, bazı parametrelerin önüne
kesme işareti koyularak kolaylıkla şu şekilde yapılabilir:
(list a (car b) 'c), a ve (car b)'yi
değerlendirir, fakat c'yi değerlendirmez. 'c'nin değerlendirilmesi,
c sembolünün kendisini döndürür, böylece sonuçta oluşan listenin
son öğesinin c olması garantilenir.
Bazen tırnak işaretli (değerlendirilmeyen) ifadelerin sayısı,
değerlendirilmesi gereken ifadelerinkinden fazladır.
"Backquote" sözdizimi işte burada devreye girer:
varsayılan tutumu değiştirir ve hiçbirşeyin
değerlendirilmemesi gerektiğini varsayar.
İstisnalar belirlenmelidir. Yani şu örnek:
`(a b c ,(car d)), (list 'a 'b 'c (car d))
ile tamamen aynı anlama gelir - a, b ve c sembolleri değerlendirilmez,
ama (car d) ifadesi değerlendirilir. "Backquote" sözdiziminde,
değerlendirilmesi gereken ifadeler/değişkenler virgül ile belirlenir.
(Buna dikkat ederseniz, "quote" sözdiziminde benzetim yapılamaz:
eğer ' yazarsanız, bunu izleyen ifadenin tamamı
tırnak işareti içine alınır ve bunun bazı bölümlerinin
istisna olarak değerlendirilmesini sağlayacak hiçbir sözdizimi yoktur.)
Yani esasen "backquote" sözdizimi sadece, neyin değerlendirilip
neyin değerlendirilmeyeceğinin varsayılan işleyişini tersine
çeviren kolaylaştırıcı bir özelliktir.
Şimdi, yukarıda verilen makro örneğini hatırlayalım.
(defmacro cure (argument)
(list 'car argument))
"Backquote" sözdizimi hakkındaki tartışmadan,
bunun şu tanıma eşdeğer olduğunu çıkarabilirsiniz.
(defmacro cure (argument)
`(car ,argument))
Artık "backquote" sözdiziminin makrolarla bağıntılı
olarak niçin çok kullanışlı olduğunu hemen
anlayabilirsiniz: makro tanımlamasının gövdesi artık gerçekte
ürettiği koda çok daha yakın. (Hatırlayın, (cure mylist)'in
bir uygulaması, derleme zamanında (car mylist) olarak neticelenir.)
Bu arada, aşağıdaki kaynak, "backquote" sözdiziminin geçmişi hakkında
çok iyi bir araştırma.
-
Makrolar, Common Lisp ve Scheme toplulukları arasındaki bir
başka, daha gizemli bir çelişmenin tam kalbinde yer alırlar.
Common Lisp'deki makrolar, istemeyerek, uygulamalarını
çevreleyen kodun değişken isimlerini de yakalayabilirler.
Bu aşırı tehlikeli gibi geliyor ama değil. Bu konu hakkında
ayrıntılı bir tartışma için lütfen Paul Graham'ın
"On Lisp" kitabına bakın - ben burada ayrıntılara girmeyeceğim.
Scheme, değişken yakalamayı önleyen, "hijyenik makrolar"
(ya da kısaca "hijyen") sözde kavramını öneriyor. Benim gördüğüm
sorun; hijyenik makroları, makroların bir geliştirmesi olarak
tanımlamak aşırı ölçüde kolay. Standart iddia şöyle:
"Common Lisp makroları değişken isimlerini yakalayabilirler;
hijyen bunu önler; böylece programlama daha güvenli olur."
Bu iddia hijyenin, sözcüksel kuşatma kavramını belirli bir
dereceye kadar anımsatması gerçeği ile bir şekilde destekleniyor.
Fakat, tüm gerçek bu değil. Bazen hakikaten
değişken isimlerini yakalamanız gerekir ve hijyen bunu
gerektiğinden daha zora sokar. Dahası, Common Lisp'te isim
yakalamayı önlemek gerçekten çok basit. Paul Graham bunu
kitabında gösteriyor, o yüzden burada çözülmesi gereken
çok ciddi bir sorun yok.
Benim iletim şu: hijyen, Common Lisp'te gerekli değildir
(ve de sunulmamıştır) çünkü güvenli makrolar yazmak kolaydır.
Teorik seviyede bu konuyla gerçekten ilgilenmediğiniz sürece,
hijyenik makrolar konusunu rahatlıkla görmezden gelebilirsiniz.
(Scheme'deki durum biraz daha farklı çünkü Scheme
değişkenleri ve fonksiyon tanımlamalarını aynı yolla
depolar - bir Lisp-1 çeşididir, yukarıya bakın.
Bu demektir ki, kazara fonksiyon tanımı yakalama olasılığı,
Common Lisp'e göre daha fazladır. Bu yüzden, bu toplulukta
bu sorunu çözmek için daha fazla ihtiyaç vardır.
Olası makro hijyen problemlerini anlatan iyi bir çalışma:
Bu çalışmada verilen örneklerin neden "Lisp-2" ve aynı zamanda
Common Lisp'te gerçekten o kadar önemli olmadığını ve hangi
durumlarda gerçekten isimleri yakalamak isteyebileceğinizi anlamaya
çalışmanız iyi bir alıştırma olacaktır.
Yukarıda bağlantısı verilen, Gabriel ve Pitman'ın fonksiyon hücreleri
ile değer hücrelerinin ayrımı konusu için de bu çalışmaya bakın.)
12. Nesne yönelimli özellikler (CLOS)
The Common Lisp Object System (CLOS),[7]
ANSI Common Lisp'in bir parçasıdır.
Fakat standarta geç eklendiğinden, bazı sağlayıcılar bunu
gerçekleştirmek için kendi zamanlarını harcadılar. Şimdilerde,
neredeyse tüm gerçekleştirmeler CLOS desteği sunmaktalar.
(Bazı sağlayıcılar bunu kendi Common Lisp'lerinin seçkin bir
özelliği olarak övüyorlar ve ben bunu bazen şaşırtıcı buluyorum.
Açıkça söylemek gerekirse, bir Common Lisp sistemi, CLOS'in tam bir
gerçekleştirmesini içermediği sürece, ANSI standardını gerçekleştirdiğini iddia edemez.)
CLOS sınıflar, alt sınıflama, çoklu kalıtım, çoklu metodlar
ve ön, art ve anlık öneriler ile tam nesne yönelimi sunuyor.
Bu, diğer nesne yönelimli programlama dilleri tarafından
sunulan özelliklerin ötesindedir.
Dahası, çalıştırma sırasında sınıf sıradüzenini
ve metod dağıtımını incelemek ve idare etmek için bir
"Meta-Object Protocol" (MOP) eklendi. Meta-Object Protocol,
ANSI Common Lisp'in bir parçası değildi ama çoğu
CLOS/MOP gerçekleştirmeleri aynı kaynaklardan türetildiği
için fiili bir standarta dönüştü.
(CLOS ve MOP, Java dili ve yansıma API [8]
gibi ayrı varlıklar değildirler ama MOP, CLOS'in bir alt kümesi görülebilir.)
CLOS ve Meta-Object Protocol için mükemmel bir açıklama,
aşağıdaki çalışmada bulunabilir:
- Linda G. DeMichiel and Richard Gabriel, The Common Lisp Object System: An Overview, ECOOP '87, Springer LNCS 276, http://www.dreamsongs.com/Essays.htmlsayfasının en altından ücretsiz indirilebilir (Richard Gabriel'a bunu ricam üzerine sağladığı için teşekkürler).
Bazı CLOS tasarım kararları için gerekçeler başka bir çalışmada bulunabilir:
- Richard P. Gabriel, Jon L. White, and Daniel G. Bobrow, CLOS: integrating object-oriented and functional programming, Communications of the ACM, Volume 34, Issue 9, 9/1991, http://doi.acm.org/10.1145/114669.114671
Jeff Dalton,
http://www.aiai.ed.ac.uk/~jeff/clos-guide.html sayfasında,
CLOS için kısa bir rehber sunuyor (MOP'yi dahil etmeden).
ANSI HyperSpec ile benzer stilde yazılmış bir MOP kaynağı
http://www.lisp.org/mop/
adresinde bulunabilir. (Bu sayfadaki çoğu dış bağlantı çalışmıyor ama kaynağın kendisi çalışıyor.)
Barry Margolin, comp.lang.lisp'te güzel bir pratik kural verdi:
-
ADD-METHOD ve ENSURE-GENERIC-FUNCTION gibi birkaç
MOP fonksiyonu ANSI CL'e sızmayı başardı ama daha fazlası değil.
"Bir şeyin CLOS'in mi yoksa MOP'nin mi temel bir parçası olduğunu
anlamak için iyi bir yol, bağımsız değişkenlerinin
sınıf, metod ya da genel fonksiyon olup olmadığına
bakmaktır. MAKE-INSTANCE veya CHANGE-CLASS gibi fonksyionlar
bu kategoriye girmezler; bir sınıf nesnesi kabul etmelerine
rağmen, aynı zamanda yerinde sınıf ismi de kabul ederler
ve MOP fonksyionları genellikle bu uygunluğu sunmazlar."
Meta-Object Protocol ile neler yapabileceğinizin
ayrıntılı (ve etkileyici) bir örneğini, aşağıdaki çalışmada bulabilirsiniz:
Bazı ek notlar:
-
Çoğul kalıtım [9] bazı insanlar
tarafından kötü bir şey olarak görülür çünkü
çözülmesi zor potansiyel isim çakışmalarına yol açar.
Çoğu programlama dili bu tür isim çakışmaları için
varsayılan bir davranış sunar ama bu çoğunlukla
yetersiz çözümlere yol açar. Common Lisp de, programcı
tarafından verilen üst sınıfların sırasına
dayanan topolojik bir sıralama yaratarak, isim çakışmaları
için varsayılan bir strateji tanımlamaktadır.
Elbette, birisi kolayca çıkıp, bu yaklaşımın yararlı
sonuçlar vermediği patolojik örnekler gösterebilir.
Yani görülüyor ki, Common Lisp'in diğer programlama
dillerininki kadar kötü bir çözümü var.
Fakat bu, CLOS'te, kullanıcı tanımlı
"metod kombinasyonları" ile telafi edilmiştir. Bir programcı
daima, her olay için metodların nasıl gönderileceğini
açıkça tanımlayabilir. (Tabii ki, bu çalıştırma zamanında
dahi değiştirilebilir.) Yani CLOS, isimlendirme çakışmalarıyla
baş etmek için çok yüksek derecede bir esneklik sunuyor.
Üst sınıfların topolojik olarak sıralanması ise sadece sistemin
yaptığı bir öneri olarak anlaşılabilir.
Çoğul kalıtımdan kaynaklanan isimlendirme çakışmalarıyla
baş etmek, kavramsal nedenlerden dolayı, her programlama
dilinde zordur. Yine Common Lisp, programcıya, ortaya
çıkacak herhangi bir durumla baş edebilmek için gerekli
tüm etkileyici gücü vererek ağır basıyor. Bunu, örneğin,
ara yüzlerin çoğul kalıtımlarının hiçbir şekilde baş
edilemeyen isimlendirme çakışmalarına yol açabileceği
Java'daki durumlarla karşılaştırın.
-
Standart metod kombinasyonları ve Meta-Object Protocol,
"aspect-oriented" programlamayı mümkün kılar. Bu bir tesadüf
değil - Gregor Kiczales, "aspect-oriented" programlamanın
yaratıcılarından, CLOS'in de tasarımcılarından biri.
AspectJ'in gelecek haftaki sürümü için beklemeyin -
şu an zaten Common Lisp ile her şeyi yapabilirsiniz! ;-)
13. LOOP imkanı
LOOP imkanı, Common Lisp'in, döngüleri Algol/Wirth
dillerine benzer tarzda ifade etmesini sağlayan başka
bir standart özelliğidir. İşte on tane yıldız bastıran bir döngü örneği:
(loop for i from 1 to 10
do (format t "*"))
Yine CLtL2 iyi bir bilgi kaynağı. Fakat hemen fark edeceksiniz ki,
çok fazla sayıda olasılık ve çok farklı biçimlerde
kombinasyonlar mevcut. Benim izlenimim, tüm ayrıntıları
öğrenmenin mantıklı olmadığı çünkü bunun aşırı uzun süreceği
şeklinde. LOOP imkanının amacı, açıkçası, bir şekilde "doğal" ve
İngilizcemsi yineleme ifadeleri sağlamak içindi ve bunun kaynak
kodu anlamayı kesinlikle kolaylaştırdığı örnekler mevcut.
(Bu aynı zamanda, yinelemenin alanı için Common Lisp'e
yerleştirilmiş alana özgü (domain specific) bir dil için güzel bir örnek.)
Aşağıda bir başka, daha da ilginç bir LOOP imkanı örneği (Matthew Danish'ten).
(defun fibonacci (n)
(loop for a = 1 then (+ a b)
and b = 0 then a ; paralel olarak ilerliyor
repeat n
collect b))
Sanırım LOOP imkanını kullanmanın amacı, sadece,
bir yinelemeyi ifade etmek için bir yol "tahmin etmek"
ve çalışıp çalışmadığını görmek. Çalışmıyorsa,
CLtL2 veya ANSI spesifikasyonlarına bakarsınız
ya da yinelemeleri veya özyinelemeleri ifade etmek için
daha Lispimtırak yollara dönersiniz
(do, dotimes, mapcar ve benzerleri ile).
Yine de bu sadece benim tahminim,
LOOP imkanının tasarımcılarının gerçek
niyetlerini bilmiyorum. (Bazıları, ayrıntıların çok çabuk
öğrenilebileceğini öne sürüyorlar ama yine de bunu kendi başıma denemeliyim.)
Bu arada LOOP yapısını öğrenmeyi başardım ve epey kullanışlı
bulduğumu söylemeliyim. Vakit alıyor ama deneyimlerime göre bu
vakte değiyor. Peter Seibel kendi kitabında LOOP için başlıbaşına
bir bölüm ayırmış, yine de pek çok durumda deneme yanılma şeklindeki
tavsiyem yeterli olacak gibi görünüyor.
14. Koşullar
Koşullar, az çok, Java benzeri dillerdeki istisnalar gibidir.
Fakat koşullar daha etkilidir çünkü koşul işleyiciler, örneğin,
Lisp çalıştırma sistemini koşulun ortaya çıktığı yerden
çalıştırmaya devam etmesi için yönlendirebilirler. Bu, istisna
işlemeye alışkınsanız, ilk bakışta garip gelebilir.
Hey, bir istisna her zaman bir sorun olduğu anlamına gelir
değil mi? İşte, Common Lisp'te koşullar sorun olmadığı
zamanlarda da bildirilebilir ama örneğin, çokişlemli (multithreaded)
bir anuyumlulaştırılması (senkronizasyonu) ya da diğer bir
kodun özel olaylardan haberdar edilmesi, ya da aklınıza
gelen yararlı her konuda da bildirilebilir. Dahası, gerçekten
sorunlar bildiren koşullar anında etkileşimli olarak ya da
programlamayla düzeltilebilir.
Sonuç olarak, çoğu nesne yönelimli programlama
dilindeki modellerin CLOS'un sadece özel bir durumu
olmaları gibi, Java'nın istisna işlemesi de yine
Common Lisp'in çok daha genel Koşul sisteminin özel bir durumudur.
Common Lisp'te koşul işleme hakkında, bazı ilginç
tarihsel eğlencelikleri de içeren, mükemmel bir açıklama
aşağıdaki çalışmada bulunabilir.
Bazı notlar:
Common Lisp, fonksiyonlardan yerel olmayan
çıkışı sağlayan catch ve throw yapılarını da
özellik olarak sunuyor. Bunlar Java'daki
try-catch-finally üçlemesiyle benzer değildirler!
Onun yerine, try-catch öbekleri yerine handler-case,
handler-bind vb. ve try-finally öbekleri yerine de
unwind-protect kullanılır. Ayrıntılar için
lütfen yukarıdaki çalışmaya ve spesifikasyona bakın.
Sırası gelmişken, Koşul sistemi "Aspect Oriented" Programlama
için de, meta programlamaya gerek kalmadan bir temel oluşturur!
15. İleri programlama teknikleri
Paul Graham'ın "On Lisp" kitabından, makro programlama
bağlamında bahsetmiştim. Bu kitap yardımcı fonksiyonların
yaratımı, yüksek derece fonksiyonlar, veritabanı erişimi,
Scheme benzeri "devam ediş"lerin benzeştirimi, çoklu işlemler,
deterministik olmama, ayrıştırma (parsing), mantıksal
programlama ve nesne yönetimi gibi Common Lisp için bir
sürü diğer ileri programlama teknikleriyle de
ilgileniyor. (Yine de kitabın çoğu makrolarla ilgili).
Bağlantıyı rahat olsun diye tekrarlıyorum.
Paul Graham, On Lisp,
http://www.paulgraham.com/onlisp.html.
16. Paketler
Java'nın, sınıfları paketler içerisinde toplamanızı ve
bunların birbirlerinden bir dereceye kadar
korunmasını sağlayan, güzel bir modül sistemi vardır.
Dahası, paket yapısı muhtemelen zip -ya da jar- dosyalarında
saklanmış olarak eşlenen dosyada -ve klasörde- yansıtılır.
Bu kolay ama ayrıntılı bir şekilde, gerektiğinde Java
çalıştırmasının sınıfları yükleyeceği yerlerin
tanımlandığı sınıf yollarını işlemeye imkan sağlar.
Common Lisp de tanımların (elbette sınıfları da içeren)
toplanacağı bir paket sistemi sunar. Fakat, hiçbir dosya
-ve/veya klasör- yapısı ile eşleşme yoktur. Common Lisp'te
paket sistemi sadece, tanımların çalıştırma anında Lisp ortamı
içerisinde nasıl düzenlendiğiyle ilgilenir.
Aslında, Common Lisp'in paket sistemi bundan daha güçlüdür
çünkü daha genel olarak sembolleri paketler içerisinde
gruplamanıza izin verir. Çünkü Common Lisp'te tanımlamalara
her zaman sembollerle erişilir, tanımlamaları paketlemek genel
paket kavramının yalnızca özel bir halidir. İşte Common Lisp'te
paketler ile başka neler yapabileceğiniz hakkında,
Kent M. Pitman tarafından comp.lang.lisp'te verilmiş güzel bir örnek.
(Aşağıdaki örneği içeren iletinin tamamını görmek için
http://makeashorterlink.com/?E3B823F91
adresine bakın.)
-
"CL bana, basit sembol verileri şeklinde, değişik türlerde paylaşım yapıp yapmadığımı denetleme imkanı sunuyor. Mesela, yerimi aşağıdaki şekilde ayırabilirim:
(in-package "FLOWER")
(setf (get 'rose 'color) 'red)
(setf (get 'daisy 'color) 'white)
(defun colors-among (things)
(loop for thing in things
when (get thing 'color)
collect thing))
(in-package "PEOPLE")
(setf (get 'rose 'color) 'white)
(setf (get 'daisy 'color) 'black)
(defun colors-among (things)
(loop for thing in things
when (get thing 'color)
collect thing))
(in-package "OTHER")
(flower:colors-among '(flower:rose people:rose flower:daisy))
=> (FLOWER:RED FLOWER:WHITE)
(flower:colors-among '(flower:rose people:daisy people:rose))
=> (FLOWER:RED)
(people:colors-among '(flower:rose people:rose flower:daisy))
=> (PEOPLE:WHITE)
(people:colors-among '(flower:rose people:daisy people:rose))
=> (PEOPLE:BLACK PEOPLE:WHITE)
Yani Common Lisp'in paket sistemi sembollerin toparlanmasıyla
ilgilenir ve böylece "yan etki" olarak tanımlamaların
toparlanmasını sağlar ama sistem parçalarının aranması ve
yüklenmesiyle hiç ilgilenmez. Common Lisp terminolojisinde,
ikinci göreve "sistem inşası" denir.
Yani lütfen bu konuda aklınız karışmasın.
Java'nın paketleri ve Common Lisp'in paketleri
sadece aynı isme sahiptirler ama farklı amaçlar
için kullanılırlar (bazı ortak yanlarla birlikte).
Common Lisp sistem inşası için sadece
temel destek tanımlar ("load" ve "require"
fonksiyonları - CLtL2 ve ANSI spesifikasyonuna bakın).
Lütfen bu konuda daha fazla bilgi için bir sonraki bölüme bakın.
17. Eksik olan ne?
ANSI Common Lisp standardı 1994'te sonuçlandırıldı ve
1995'te yayınlandı. Bu Java'nın köşeden göründüğü fakat
henüz halka açılmadığı zamanlardı. Bu aynı zamanda Internetin
ticari yükselişinden de önceydi. Şurası açık ki, son yedi senedir,
programlama desteği birçok yönde ilerledi.
Maalesef bu sürede Common Lisp'in "resmi" standartlaştırılması
devam etmedi. ANSI Common Lisp'in içermediği birçok şey,
şu anda diğer, daha moda programlama dillerinde mevcut.
Bu özelliklerin en üstünde şunlar var: düzgün bir modül ("sistem inşası")
olanağı, Unicode desteği, ortamdan bağımsız grafik kullanıcı ara yüzü
kütüphanesi, soketler ve TCP/IP, XML, Ağ Hizmetleri ve
benzeri (en çok sevdiğiniz özelliğinizi siz ekleyin).
Yine de, Lisp dünyası bu zaman zarfında yerinde saymadı
- bir şeyin ANSI Common Lisp standardında belirtilmemesi,
onun var olmadığı anlamına gelmez.
Yaygın kullanılan iki sistem inşa olanağı ASDF
(http://www.cliki.net/asdf)
ve MK-DEFSYSTEM'dir (http://www.cliki.net/mk-defsystem).
Bunlara ilaveten, bazı Common Lisp gerçekleştirmeleri
kendi sistem yorumlama destekleriyle birlikte geliyorlar.
Allegro Common Lisp, LispWorks ve CLISP Unicode desteği sunuyorlar.
CLIM; Franz, Xanalys ve Digitool gibi bazı dağıtımcılar tarafından
desteklenen, platformdan bağımsız bir grafik kullanıcı ara yüzü kütüphanesi.
En ciddi Common Lisp gerçekleştirmeleri soketler için destek ve
daha ileri ağ bağlantısı imkanları sağlıyor. CLISP fastgci
için destek sağlıyor. CL-XML, XML ile ilgilenmek için bir kütüphane.
Yani temel ileti şu: eğer kütüphaneye ihtiyacınız varsa
Google'da biraz araştırma yapın, kullanabileceğiniz birşeyler
bulabilirsiniz. Ayrıca aşağıda verilen bazı bağlantılara da bir göz atın.
Bölüm III: Bağlantılar
Televizyon ekranı aklın gözünün retinasıdır.
Bu yüzden, televizyon ekranı beynin fiziksel yapısnın bir parçasıdır.
Bu yüzden, televizyon ekranında görünen herşey onu izleyenler için ham deneyime dönüşür.
Bu yüzden, televizyon gerçekliktir ve gerçeklik televizyondan daha azdır.
- Videodrome'da Profesör O'Blivion , David Cronenberg'den
İşte yararlı ve/veya ilginç bağlantıların bir listesi.
Hepsinden olmasa da bazılarından yukarıdaki yazıda zaten bahsedildi.
18. Kişisel web siteleri
-
Bill Clementson'ın sayfası, http://bc.tech.coop
-
Richard Gabriel'ın sayfası, http://www.dreamsongs.com - Common Lisp'in babalarından biri, sitesinde birçok ilginç yazı bulunabilir
-
(Önceden Erann Gat olarak tanınan Lisp hacker'ı) Ron Garret'in http://www.flownet.com/gat/ - Lisp, Java ve C++'ın başarım özelliklerini karşılaştıran çalışmayı yönetti
-
Paul Graham'ın sayfası, http://www.paulgraham.com - "ANSI Common Lisp" ve "On Lisp" kitaplarının yazarı, ayrıca birçok ilginç makale sunuyor
-
Rainer Joswig'in sayfası, http://lispm.dyndns.org/
-
David B. Lamkins'in sayfası, http://psg.com/~dlamkins/ - ücretsiz yararlanılabilen "Successful Lisp" online eğitimin yazarı
-
Nick Levine'ın sayfası, http://www.nicklevine.org/
-
John McCarthy'nin sayfası, http://www-formal.stanford.edu/jmc/ - 1950'lerde Lisp'i icat etti
-
Peter Norvig'in sayfası, http://www.norvig.com
-
Andreas Paepcke'nin sayfası, http://www-db.stanford.edu/~paepcke/
-
Kent Pitman'ın sayfası, http://www.nhplace.com/kent/ - Lisp koşul sistemi projesinin lideriydi
-
Kevin Rosenberg'in sayfası, http://b9.com/
-
"Common Lisp: An Interactive Approach" isimli e-kitabın yazarı
Stuart C. Shapiro'nun sayfası, http://www.cse.buffalo.edu/pub/WWW/faculty/shapiro/
-
Mark Watson'ın sayfası, http://www.markwatson.com/ - ücretsiz yararlanılabilen "Loving Lisp - the Savy Programmer's Secret Weapon" kitabının yazarı
-
Edi Weitz'ın sayfası, http://weitz.de/
19. Common Lisp Kaynakları
20. Altyapı bilgisi
-
Common Lisp - Mitler ve Efsaneler, http://www.lispworks.com/products/myths_and_legends.html
-
Devam edişler, http://c2.com/cgi/wiki?CallWithCurrentContinuation - WikiWikiWeb'de bir açıklama (http://c2.com/cgi/wiki)
-
comp.lang.lisp için SSS, http://www-jcsu.jesus.cam.ac.uk/~csr21/lispfaq.html
-
Feyerabend projesi, http://www.dreamsongs.com/Feyerabend/Feyerabend.html
-
Guy Steele ve Gerald Jay Sussman'ın özgün 'lambda çalışmaları', http://library.readscheme.org/page1.html - bu çalışmaların tarihi 1970'lere kadar gidiyor ve Scheme'in değişik yönlerini tartışıyorlar; bazıları Common Lispçilerin de ilgisini çekebilir
-
Sözcüksel kapsam, dinamik kapsam, (sözcüksel) kuşatma, http://c2.com/cgi/wiki?ScopeAndClosures - WikiWikiWeb'de bir açıklama (http://c2.com/cgi/wiki)
-
Lisp Scheme Farklılıkları, http://c2.com/cgi/wiki?LispSchemeDifferences - WikiWikiWeb'de Common Lisp'in Scheme ile karşılaştırılması (http://c2.com/cgi/wiki)
-
Common Lisp/Scheme Karşılaştırması, http://makeashorterlink.com/?E2E9254F6, Ray Dillinger'dan mükemmel bir karşılaştırma
-
Lisperati - Lisp programlama ilgili bir çizgi (!) öykü ;), http://www.lisperati.com/
-
Meta Object Protocol, http://c2.com/cgi/wiki?MetaObjectProtocol - WikiWikiWeb'de Common Lisp'in MOP'si için bir tartışma (http://c2.com/cgi/wiki)
- İnsan-Belge Etkileşim Alanı (Xerox PARC)yayınları,
http://www2.parc.com/istl/groups/gir/hdipublications.shtml - CLOS'un öncüllerinden biri olan LOOPS ile ilgili
pek çok makale içerir.
-
LOOPS ile ilgili bir sayfa, güzel fotoğraflar var: http://www2.parc.com/istl/members/stefik/loops.html
-
Tail çağrıları, tail özyinelemesi, http://c2.com/cgi/wiki?TailCallOptimization - WikiWikiWeb'de bir açıklama (http://c2.com/cgi/wiki)
-
Wikipedia'daki Common Lisp maddesi, http://en.wikipedia.org/wiki/Common_Lisp
21. Havuzlar, bağlantılar, yazılımlar
-
*hyper-cliki* - bir Lisp wiki sistemi, http://lisp.tech.coop/, Common Lisp dünyasının en önemli portal sitelerinden. Common Lisp gerçekleştirmelerinin bir listesini ve çok daha fazlasını içerir.
-
CLiki, http://www.cliki.net/, Common Lisp'te gerçekleştirilmiş ücretsiz yazılımlar için bağlantılar ve kaynaklar kolleksiyonu
-
Common-Lisp.net, http://common-lisp.net/, Common Lisp'çiler için, SourceForge dünyanın kalanı için ne ifade ediyorsa o
-
The Common Lisp Cookbook, http://cl-cookbook.sourceforge.net/
-
Common Lisp Hypermedia Server, http://www.ai.mit.edu/projects/iiip/doc/cl-http/home-page.html, Common Lisp'te gerçekleştirilmiş, tam donanımlı, açık kaynak bir web sunucusu
-
Common Lisp Open Code Collection, http://clocc.sourceforge.net
-
The Common Lisp Open Source Center, http://opensource.franz.com/
-
setf.de Lisp Tools, http://www.setf.de/, CL-XML, bnf-tabanlı bir ayrıştırıcı, java2lisp ve çeşitli diğer araçları içeriyor
-
CLUnit, http://www.ancar.org/, bir birim deneme çerçevesi (JUnit'e benzer)
-
JACOL, http://jacol.sourceforge.net, soketler aracılığıyla Java ve Common Lisp etkileşimi için bir çerçeve
-
UFFI, http://uffi.b9.com/, Common Lisp programlarını C-dili uyumlu kütüphaneler ile araryüzlemek için bir paket
-
Lisp ve Apache ile nasıl dinamik web siteleri yaratılır, http://lisp.t2100cdt.kippona.net/lispy/home
-
BioLisp.org, http://www.biolisp.org/, BioComputing'de akıllı uygulamalar
-
ACL2, http://www.cs.utexas.edu/users/moore/acl2/, Common Lisp'in uygulanabilir bir alt kümesi için yarı-otomatik bir teorem kanıtlayıcı
-
Dynamic Learning Center, http://www.dynamiclearningcenter.com/, öğrenciler ve öğretmenler için on-line eğitim kaynakları
22. Scheme bağlantıları
23. Telif hakkı konuları
Online Yazarlar için Telif Hakkı Rehber, yazan Gene Michael Stover, http://lisp-p.org/copyright/
Teşekkürler
Taslak sürümde bir çok yararlı geribildirim sağlayan
(alfabetik sırayla) Tom Arbuckle (http://www.sqrl.ul.ie/staff.html),
Joe Bergin (http://csis.pace.edu/~bergin/) ve
Richard Gabriel'e (http://www.dreamsongs.com/) çok teşekkürler.
Seung Mo Cho'ya, Korece çeviri için teşekkür ederim.
Daha da fazla geribildirim için Paolo Amoroso, Marco Antoniotti,
Tim Bradshaw, Christopher Browne, Thomas F. Burdick, Wolfhard Buß,
Bill Clementson, Matthew Danish, Biep Durieux, Knut Aril Erstad,
Frode Vatvedt Fjeld, John Foderaro, Paul Foley, Erann Gatt,
Martti Halminen, Bruce Hoult, Arthur Lemmens, Barry Margolin,
Nicolas Neuss, Duane Rettig, Dorai Sitaram, Aleksandr Skobelev,
Thomas Stegen, Gene Michael Stover, Rafal Strzalinski, Raymond Toy,
Sashank Varma ve Espen Vestre'ye ilaveten teşekkürler.
(Çoğu comp.lang.lisp'te etkin katılımcılar)
Çevirenin ve Editörlerin Notları
Bu belge, özgün yazarın izniyle Hayrettin Gürkök
tarafından çevrilmiş, son düzenlemeler (soyadı alfabetik
sırasına göre) Seda Çelebican, Hayrettin Gürkök, Bülent Murtezaoğlu
ve Emre Sevinç tarafından gerçekleştirilmiştir. Bazı Türkçe terimlerin karşılıkları
ve açıklamalar aşağıda belirtilmiştir.
[1]
Lexical closures
[2]
Continuations
[3]
Tail recursions, bkz. http://en.wikipedia.org/wiki/Tail_recursion
[4]
Boolean
[5]
Statement
[6]
Expression
[7]
Common Lisp Nesne Sistemi
[8]
Reflection API
[9]
Multiple inheritance
*
Hesaplama teorisinde bir programlama sistemi ya da herhangi
bir formel mantıksal sistem eğer evrensel Turing makinasına
denk bir hesaplama gücüne sahipse, Turing-tam olduğu söylenir.
Başka bir deyişle sistem ve evrensel Turing makinası birbirlerine
öykünebilirler (emulate each other). Bkz.
http://en.wikipedia.org/wiki/Turing_completeness
|
|