2012-12-07 12 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ì.

Problemi correlati