20101230

Web icin Common Lisp

Lisple ugrasmaya basladigimdan beri yapmak istedigim bir sey vardi kafamda. Tamamen lisple bir web uygulamasi yazmak. Bir lisp server ve kolay html ciktisi alabilecegim bir lisp kutuphanesi ile baslayayim dedim. En bastan bir web server yazcak degilim, daha dili tam bilmiyorum ...

O yuzden bir pure lisp web server olan Hunchentoot kurmakla basladim ise... Yok yaa... yalan konusuyorum.. Ilk once lisp icin ortam hazirlamakla basladim. Gorundugu kadar kolay degil... Konsoldan calismaya alisik degilseniz ise hic kolay degil. Hele Quicklisp'ten once isler daha da zordu. (xach'ten Allah razi olsun :))
Neyse kurulum islerini gecicem. Orda vakit harcamak istemem. Ozetle su an lispe baslicak birisi icin en ideal ortam: SBCL + Quicklisp + Emacs + Slime (:quicklisp-slime-helper). Tabi bir de Debian-based bir Linuxunuz olursa ya da bir BSDniz cok daha iyi olur. (paket isleri kolay oluyor o yuzden)

Hunchentoot'ta kalmistik ... Quicklisp kurduktan sonra sisteme Hunchentoot kurmak:
   (ql:quickload :hunchentoot) 
gibi tek satirlik bir komut. Quicklisp sayesinde tum dependencylerle birlikte Hunchentoot geliyor. Ama onu calisir hale getirmek icin biraz ugrasmak gerekti. Kendim bayagi ugrastiktan sonra Googledan bir bloga denk geldim. Kurulumu cok guzel ozetlemis. Onun da yardimiyla Huncentootu calisir hale getirebildim.

Kurulum icin linkini verdigim bu blogu takip edebilirsiniz. Benim burda yaptigim ufak tefek bazi degisiklikler oldu. Ilk olarak, kuruluma basladigimda Common Lisp implementation olarak SBCL kullanmiyordum, CMUCL kullaniyordum o yuzden SBCL'e ozel kodlari her yerde calisacak sekilde duzenledim.

Ilk basta CMUCL kullanmamin sebebi de SBCL + Debian + Quicklisp uclusunde sorun yasamamdi. Debian paketleri zamanin bir hayli gerisinde oldugu icin sorunlar cikiyordu. O yuzden kisa yoldan bi CMUCL source indirip kurdum. Ama CMUCL ile Hunchentoot arasinda hizla ilgili bir sorun oldu. Hunchentoot requestlere cok gec cevap veriyor hatta bazen vermiyordu. Bu yuzden tekrar SBCLe dondum.

Bu sefer apt-get install sbcl yerine kaynak koddan derlemek zorunda kalarak SBCLin guncel versiyonunu yukledim. Bu sefer her sey yolunda gibiydi ve oyle de oldu. Ama daha once SBCLe ozel kodlari geri aldim cunku onlarin performansi daha iyiydi.

Neyse ki artik weble ilgili bir seyler yapmaya baslayabilirdim.

Blog'da anlatildigi gibi Remote REPL'e baglandiktan sonra ilk denedigim kod:

(hunchentoot:define-easy-handler (my-page :uri "/lisp")                                                                                        
    ()
  "lisp...")
oldu. Yani http://localhost/lisp linkine gittigimde karsima lisp... yazan sayfa cikmaya basladi... :)

Daha sonra biraz html yazayim dedim... Elle html yazmak hic hos degil... buyuktur kucuktur filan yazarak yapilacak is degil yani... O yuzden biraz arastirdim cl-who kutuphanesi varmis. Lisp kutuphaneleriyle ilgili cok fazla dokuman bulamadigim icin en iyi dokumantasyon kodun kendisidir mantigiyla dogrudan kaynak koduna baktim. Kod gayet anlasilir ama nedense biraz uzun geldi bana... yani "ne gerek var yahuu" gibilerinden bir dusunce gecti icimden. Daha sonra da kisasini kendim yazmaya basladim... :) Yazdimda gercekten de benim isime yarayacak olan seyi 65 satirlik bir kodla yazdim. (bknz :dsgner) Elbette ki cl-who benim :dsgner 'dan daha kapsamli ama benim isime bu kadari yetiyor su an.. Hem yazmasi zevkliydi ...

En son


(hunchentoot:define-easy-handler (my-page :uri "/lisp/mypage")                                                                                        
             (msg)                                                                                                                                             
           (:html ()                                                                                                                                           
             (:head ()                                                                                                                                         
               (:title ()                                                                                                                                      
                 "Welcome-to-lisp"))                                                                                                                           
             (:body (:bgcolor "#CCCCCC")                                                                                                                       
               (:a (:href "http://asdr.me/lisp/mypage?msg=here")                                                                                               
                 (format nil "Click baby... ~A" msg)))))


gibi bir kod yazabilecek duruma geldim. Peki sirada ne var? Sirada verilerini Cassandra'da saklayan bir blog yazma isi var. Ama once bir Coomon Lisp Cassandra Client yazmam gerekecek... :)

--asdr

20101124

Dynamic Scoping in Lisp

Iki hafta once siparis verdigim kitap dun elime gecti: Let Over Lambda, Doug HOYTE.
Bekledigimden cok daha guzel bir kitap cikti. Ilk okudugum bolumunden dikkatimi ceken seyleri yazmak istedim.

Bolum closure'lar uzerine.. Ben closure'lari JavaScriptten hatirladigim icin ilk olarak ordaki gibi dusundum ama asagidaki ornek JS de implicit olarak yapilmiyor. JSdeki closure'la Lisp'i karistirmamak lazimmis (zaten tam closure degil dynamic scoping) . Lisp'in bunu bu sekilde yapmasi nedense hosuma gitti...

;;LISP KODU;;
(defvar *temp-special* 1)

(defun temp-special-returner()  
  *temp-special*)
(temp-special-returner) ;;;donen deger: 1


;; let ile normalde lexical variable yaratiyoruz
;; ama asagida durum farkli...
(let ((*temp-special* 2)) 
  (temp-special-returner));;donen deger: 2 ****

(temp-special-returner);;donen deger: 1 *****


Bunu JSde yaziyim dedim bir de; bakalim sonuc ne olacak diye.

special = 1;

function specialReturner() {
  return special;
}

alert(specialReturner());//donen deger: 1

alert(
(function(special) {
  return function() {
    return specialReturner();
  })(2)()
);//donen deger: 1

alert(specialReturner());//donen deger: 1