2012-12-07 3 views
7

Sto cercando di creare query Datalog a livello di codice, ma mantenere in esecuzione nel problema che illustrerò con una funzione di esempio:Perché clojure aggiunge qualificatori di namespace ai nomi all'interno di un backquote?

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

Quando eseguo (test espr-3), mi sarei aspettato l'uscita:

[?entity 3 ?value] 

Ma invece, ottengo

[mynamespace/?entity 3 mynamespace/?value] 

Il che, ovviamente, non è quello che voglio. C'è un modo per dire clojure "per favore basta citare la lista ed espandere le variabili che ti dico?"

+1

Per quanto riguarda il motivo, è per impedire agli utenti (* cough * you) di rompere accidentalmente i tuoi macro definendo funzioni e/o variabili con lo stesso nome che stai utilizzando. – Cubic

+0

@Cubic, d'accordo. Per quanto ho capito, questa è una sorta di compromesso tra i macro igienici Scheme e i comuni sistemi macro Common Lisp: le definizioni macro sembrano quasi esattamente come quelle Common Lisp (questo è buono, dal momento che le macro Scheme sono più difficili da scrivere IMO), ma per impostazione predefinita c'è un certo livello di igiene presente - i simboli non vengono catturati ciecamente ma sono invece prefissati con namespace. Ed è sempre possibile ricorrere a semplici sostituzioni quando necessario (ad esempio per macro anaforiche). –

risposta

9

Sì, c'è.

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

Qui prima unquote la citazione sintassi e poi citare subito il simbolo (~' costrutto) di nuovo. Il risultato è un simbolo di namespace.

È equivalente a quanto segue, che spiega come funziona:

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

Quello che stai cercando è la libreria backtick da Brandon Bloom https://github.com/brandonbloom/backtick

E 'stato costruito per il problema esatto descrivere. Fornisce un comando chiamato 'template' che funziona come backtick ma senza la funzione namespacing.

In Clojure, la risoluzione di quasiquotation e namespace sono mescolate insieme in una singola funzione. Ciò ha grandi vantaggi per la scrittura di macro in un linguaggio come Clojure, che è un "Lisp-1" (al contrario di Common Lisp, che è un "Lisp-2", con spazi dei nomi separati per funzioni e variabili.)

Concordo anche sul fatto che sarebbe stato meglio non confondere queste caratteristiche, ma avrebbe reso meno elegante la scrittura di macro in Clojure, quindi posso capire perché funziona così.