osa1 github gitlab twitter cv rss

Clojure'da reader macroları

October 28, 2011 - Tagged as: lisp, tr.

Kendime not: Clojure’da, biraz hacky bir şekilde de olsa reader macroları tanımlanabilir. Örneğin < ile başlayıp > ile biten, arasındaki karakterleri string’e dönüştüren bir reader macrosu şu şekilde tanımlanabiliyor:

(defn reader-macro [ch fun]
  (let [dm (.get
             (doto (.getDeclaredField clojure.lang.LispReader "macros")
               (.setAccessible true))
             nil)]
    (aset dm (int ch) fun)))
(defn native-string [rdr letter-u]
  (loop [s nil
         p \space
         c (char (.read rdr))]
    (let [s (str s p)]
      (if (= c \>)
        s
        (recur s c (char (.read rdr)))))))
(reader-macro \< native-string)

Burda reader-macro fonksyionu, clojure.lang.LispReader sınıfının macros fieldını(IFn[^256] erişilebilir hale getirip(reflection), reader macrosunun çağıracak karakterin(bizim durumumuzda <) yerine okuyacak fonksionu ekliyor. Bizim fonksiyonummuz native-string.

Reader fonksyionunu ilk parametresine clojure.lang.LineNumberingPushbackReader geliyor. read, readLine, unread gibi methodları var. İkinci parametresini çözebilmiş değilim.

Clojure’da bir de dispatch macroları var, bunların tek farkı(muhtemelen bunların vermek istediği bir mesaj var ama ben çözemedim henüz), dispatch macroları # ile başlıyor. Yukarıdaki kodda, reader macrosunu clojure.lang.LispReader.macrosa değil de, clojure.lang.LispReader.dispatchMacrosa ekleyerek dispatch macroları genişletilebilir. Kurcalamak isteyen olursa, LispReader.java.

Kaynaklar: 1, 2


Clojure’da reader macroları bir süredir tartışılıyor aslında. Genel olarak, okunması/anlaşılması zor koda sebep olduğundan, namespace desteğinin olmamasından, Clojure’un zaten çok kullanılan veri yapıları için reader macrolarına sahip olmasından ve benzer başka sebeplerden dolayı reader macrolarımızı tanımlayamıyoruz şu anda. Şurda ilgili bir IRC logu var, şurda da bir mail(bir mail daha vardı ama bulamadım şimdi).

Açıkçası bana bu sebepler mantıklı geliyor. Clojure’a reader macroları gelsin istemem. Common Lisp’den hevesini alamamış biri olarak bu şekilde reader macrolarıyla oynamak bana yetiyor şimdilik :) .