2011-11-14 20 views
5

Verilen ifadelerden birini rastgele seçip değerlendiren bir makro tanımlamak istiyorum. Örneğin, "1" yarısı kadar zaman ve diğer yarısı "2" yazdırmalıdır.Clojure: Alınan bir formu yerel kapsamda nasıl değerlendirilir?

kullanıyorum çalıştı,

(defmacro equal-chance 
    [& exprs] 
    `(rand-nth '~exprs)) 

ama bu daha ziyade onu değerlendirmek yerine, alıntılanan biçimlerinden biri döndürür (yani aslında "1" baskı yerine (println "1") dönecekti). Bağlantıları koruduğu için eval kullanamıyorum. Örneğin, X simgesinin çözümlenemediğinden şikayetçi olur.

Yerel kapsamdaki teklif formunu değerlendirmenin bir yolu var mı? Ya da belki bunun hakkında daha iyi bir yolu var mı?

cevap

2

yalnızca derleme zamanında var olan bir sözcük ortamında bir çalışma zamanı değerini değerlendiremez. Çözelti eval yerine fn yerine quote ve bir işlev çağrısını kullanmaktır: Bu işleri

(defmacro equal-chance [& exprs] 
    `((rand-nth [[email protected](map (fn [e] `(fn [] ~e)) exprs)]))) 

yolu ((rand-nth [(fn [] e1) (fn [] e2) ...])) içine (equal-chance e1 e2 ...) genişleterek gereğidir.

+0

bu harika çalışıyor! bunu asla kendi başıma düşünemezdim, teşekkürler – Ken

+0

Fn/call yerine bunun yerine gecikme/kuvvet kullanmayı tercih ediyorum: '(force (rand-nth [~ @ (harita (kısmi liste \' gecikme) exprs)])) ' – amalloy

1

Yalnızca çağrıyı rand-nth veya ifadelere alıntılama. İstediğin bu yapar:

(defmacro equal-chance 
    [& exprs] 
    (rand-nth exprs)) 
+2

Bu, tüm durumlar için geçerli değildir. (dotimes [i 10] (eşit şans 1 2 3)) 'bu sayılardan 10 kez geri dönecektir. – Ken