2013-04-03 18 views
5

Clojure'da iki veya daha fazla s ifadesi döndüren bir makro (veya varolanını kullanarak) yazmanın bir yolu var mı?İki veya daha fazla s ifadesi döndürmek üzere küme makrosu

Örnek.

(map * (repeat 2 (range 10))) 
:

(map * (range 10) (range 10)) 

Şimdi denemek ve bir parametre olarak daha sonra (şimdilik 2) güç sağlar, böylece tekrarı kullanmak istiyorum: Ben ilk 10 kareler üretmeye çalışıyorum Say

Yukarıdakiler, tekrarı olarak çalışmamaktadır, iki aralıkla değil, iki aralıklı tek bir ifade döndürür.

Lütfen "ilk 10 kareyi iade et" işlevinin alternatif uygulamalarını sağlamaz. Bu tür durumlarla veya genel olarak uygulanabilir geçici çözümlerle ilgilenmek için deyimsel yollarla ilgileniyorum.

Ben aşağıda patlayabilir Ben uygulamak için bir yol arıyorum varsayalım:

(explode '(a b c)) ;; evals to a b c 
(map * (explode (repeat 2 (range 10))) 
+0

Sorunuz biraz kafa karıştırıcı.İş görmek istediğiniz sözdizimine bir örnek vermeniz yararlı olacaktır; Şimdilik, Clojure'da belirli tanımları olan 'map' ve' repeat' işlevlerini kullanın. – JohnJ

+0

@JohnJ Mesajımın güncellenmiş kuyruğunu gör –

cevap

4

Tek makro bunu yapamaz.

Makro, 'un bir s ifadesini aldığı ve onu başka bir s ifadesine dönüştüren bir işlevdir. Girdiler herhangi bir ifade dizisi (semboller, primitifler, diğer ifadeler vb.) Olabilir ve çıktı, orijinal makro çağrısının yerine eklenen tek bir ifadedir.

genel olarak makro bütün formu

(your-macro-here (map * (repeat 2 (range 10)))) 

iki makro, tüm dış formunu kapsar ifadeleri üretir ve diğeri varsa, dış makro harita ve dönüştürmeye çağrıyı çevreleyecek zorunda kalacak Makro sonucunu içeren tek bir ifadeyi, örneğin iki aralığınızda bulabilir ve bağımsız bir ifade olarak bir seviyeye kadar kaldırabilirsiniz. Bunu pratikte yapmanızı öneremedim, sadece makroların yeteneklerini göstermeye hizmet ediyor.

2

Arthur'un dediği gibi, tam olarak makrolarla aradığınız şeyi yapamazsınız. Bu formlarla ne yapmak istediğinize bağlı olarak geçici çözümler mümkündür. Makro tarafından üretilen çoklu formları değerlendirmek isterseniz, örn. Demirbaş kodu basitleştirmek için, bir do formda olanlar birden fazla form sarabilirdiniz:

(defmacro defn-foos [& foos] 
    `(do [email protected](map (fn [foo] `(defn ~foo [])) foos))) 

(defn-foos my-fn-1 my-fn-2) 
;; expands as: 
;; (do (defn my-fn-1 []) 
;;  (defn my-fn-2 [])) 

bir işlev çağrısında pozisyonel argümanlar olarak genişletilmiş formları kullanmak istiyorsanız, bunu daha sonra en iyi bahis yapmak göründüğü gibi Muhtemelen bir list'a sarmak ve bir listeye konumsal argümanlar olarak bir listeyi açmak için apply kullanın.

Bunun nasıl çalıştığını görmek için, orijinal söz konusu ikinci örnek trivially apply kullanarak çalışmak üzere modifiye edilebilir unutmayın: ifadeli olarak

(apply map * (repeat 2 (range 10))) 
İlgili konular