2012-12-07 18 views
7

Ben programlı datalog sorguları oluşturmak için çalışıyorum, ama ben bir örnek işlevi ile gösterilecektir sorun haline çalışmasını sağlamak am:Neden clojure ad alanı niteleyicileri bir backquote içindeki isimlere ekliyor?

(defn test-expr [attribute] 
    `[?entity ~attribute ?value]]) 

koşuyorum (test-expr 3), ben çıkışını beklenir:

[?entity 3 ?value] 

Ama onun yerine, ben açıkçası ne istiyorum değil

[mynamespace/?entity 3 mynamespace/?value] 

olsun. Clojure'a söyleyebilmenin bir yolu var mı "lütfen sadece listeyi alıntıla ve sana anlattığım değişkenleri genişlet" mi?

+1

Nedeni, kullanıcıların (* öksürük * siz) yanlışlıkla kullandığınız aynı ada sahip işlevleri ve/veya değişkenleri tanımlayarak makrolarınızı kırmasını önlemektir. – Cubic

+0

@Cubic, kabul etti. Anladığım kadarıyla, bu, Scheme hygienic makroları ve Common Lisp düz makro sistemleri arasında bir tür uzlaşmadır: makro tanımları, Common Lisp olanlara benzemektedir (Scheme makrolarının IMO yazması daha zor olduğundan, bu iyi bir şeydir), ancak varsayılan olarak belirli bir düzeyde hijyen mevcut - semboller körü körüne yakalanmamakta, ancak bunun yerine isim alanı ile ön eklenmiştir. Gerektiğinde (örneğin, anaporik makrolar için) düz sübstitüsyonlara geri dönmek her zaman mümkündür. –

cevap

9

Evet, var. İşte

(defn test-expr [attribute] 
    `[~'?entity ~attribute ~'?value]) 

ilk sözdizimi tırnak unquote ve sonra hemen tekrar sembolü (~' yapı) alıntı. Sonuç, isim-alanı olmayan semboldür.

O hangi nasıl çalıştığını açıklar, aşağıdakilere eşdeğerdir:

(defn test-expr [attribute] 
    `[~(quote ?entity) ~attribute ~(quote ?value)]) 
4

Ne aradığınız Bu, tamamen aynı sorun için inşa edilen Brandon Bloom https://github.com/brandonbloom/backtick

tarafından backtick kütüphanesidir tanımlamak. Backtick gibi çalışan ancak ad doldurma aracı olmadan çalışan 'template' adında bir komut sağlar.

Clojure'da, eşzamanlılık ve ad alanı çözünürlüğü tek bir özellikte birlikte karıştırılır. Bu, makroları "Lisp-1" olan (Lisp-2'nin aksine, "Lisp-2" nin aksine, işlevler ve değişkenler için ayrı ad alanlarına sahip olan) bir makroda yazmak için büyük yararlara sahiptir.

Ayrıca, bu özellikleri karıştırmamanın daha iyi olabileceğine katılıyorum, ancak Clojure'daki makroların daha az zarif olmasını yazabilirdi, bu yüzden neden böyle çalıştığını anlayabiliyorum.