Makrolar kullanılmasının bir nedeni, kullanıcının her şeyi teklif etmek zorunda kalmadan işlev ve sembol adları yazabilmesidir. Bu örneği from the Clojure Cookbook atın:
; Routing
(defroutes main-routes
(GET "/" [] (index))
(GET "/en/" [] (index))
(GET "/fr/" [] (index-fr))
(GET "/:greeting/" [greeting] (view greeting)))
index*
sembollerin tümünün yanı sıra view
ve greeting
GET
bir işlev olsaydı alıntı gerekecekti: işlevi çalıştırılmadan önce fonksiyon argümanları değerlendirilir yana
; Routing
(defroutes main-routes
(GET "/" [] '(index))
(GET "/en/" [] '(index))
(GET "/fr/" [] '(index-fr))
(GET "/:greeting/" '[greeting] '(view greeting)))
Form okunduğunda, (index)
ve diğerleri tarafından değerlendirilecektir. Ayrıca, her bir HTTP isteğinde greeting
değişkeni değişecektir, bu nedenle açık bir şekilde önceden bilinmemektedir. Makro ayrıca, normal bir işlevle (normalde) mümkün olmayan tüm yıkıcı büyü ile de ilgilenir.
(GET "/:greeting/" [greeting] (view greeting))
normal "Clojure kod" değil:
genellikle kafa karıştırıcı (ve iyi başlayanlar açıkladı değildir) şey gibi bir satır olmasıdır. Bunun yerine, GET
makrosunun "yasal" Clojure kodunun nasıl üretileceğine dair talimatlar olarak kullanacağı ve kullanacağı bir tür (elverişli bir şekilde Alana Özgü Dili veya DSL) kısa yoldur. DSL, Clojure çok daha kısa, daha basit, & Clojure derleyici tarafından üretilen Java Bytecode veya makine montaj dili kodundan daha uygun olduğu gibi, bir insan için son oluşturulan koddan daha uygun olan daha kısa, daha basit, & JVM tarafından üretilmiştir.
Kısacası, her makro, DSL'i basit bir Clojure haline getiren bir "ön derleyici" dir; bu, daha sonra Clojure derleyicisi tarafından Java bayt kodu oluşturmak için alınan yongadır.
GET
sembol bir işlev ne de makro gibi, ama işaretleyici sadece bir tip ne oldu böylece
defroutes
makro içine makro büyü tüm koymak için yeniden düzenlenmiştir olabilir, söyledikten Uygulamada
:get
anahtar kelime. Bir kullanıcı olarak, bu tür uygulama detayları normalde çok fazla önemli değildir.
Güncelleme
Bir işlev çalışmak veya çok garip olmaz sadece makro kullanmak en iyisidir. Karar verici faktör, genellikle çıplak (belirtilmemiş) semboller kullanmak istiyorsa, ancak bunları önceden değerlendirmezse belirleyici faktördür. Çekirdek Clojure kendisi defn
, for
, and
, or
, when
ve diğerleri dahil olmak üzere diğer dillerde "yerleşik ins", birçok yapılar için makro kullanır.
Ayrıca makro bazı şeyler bir işlev yapamaz unutmayın can, böyle filter
gibi yüksek bir dereceden işleve bir parametre olarak.
Özetle, bir fonksiyon, bir Davranışı tanımlar. Makro, bir dil uzantısını tanımlar.
Eğer GET bir fonksiyon olsaydı, '' (tebrik selamlama) 'hiçbir anlam ifade etmezdi. “GET” /: selamlama ”(fn [req] (istek [[tebrik] req] (selamlama))))), hantal ama imkansız olmayan bir şey yazmanız gerekir. – amalloy
İşlev yaklaşımının çoğu özellik için 'eval' kullanması gerekecek, bu nedenle makro çözümü büyük ölçüde tercih ediliyor. –
@AlanThompson - tamamen merak. Makroların büyük bir hayranı değilim çünkü çoğu zaman gerçekten neler olduğunu engellediklerini düşünüyorum. Projeler onları yoğun olarak kullandığında daima ilgilenir (tasarım kararları vb.). Sadece bidi'yi buldum - veri yapısı yaklaşımı bana ruhani düzeyde konuşur. – beoliver