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")
(true))
(.setAccessible nil)]
aset dm (int ch) fun)))
(defn native-string [rdr letter-u]
(loop [s nil
(\space
p char (.read rdr))]
c (let [s (str s p)]
(if (= c \>)
(
srecur s c (char (.read rdr)))))))
(\< native-string) (reader-macro
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.macros
a değil de, clojure.lang.LispReader.dispatchMacros
a ekleyerek dispatch macroları genişletilebilir. Kurcalamak isteyen olursa, LispReader.java.
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 :) .