2011-01-10 15 views
6

Voglio creare un DSL in Elisp cercando qualcosa di simile:Come creare un DSL in Elisp

(install 
;; do install 
) 

(uninstall 
;; do uninstall 
) 

Tuttavia, dal momento che Elisp hanno un namespace globale, questa non è una buona idea. E prefiggendo le funzioni come questa, è così dannatamente brutto.

(package-install 
;; do install 
) 

(package-uninstall 
;; do uninstall 
) 

così ho pensato come un compromesso tutti i comandi potrebbero essere avvolto in un comandi chiamare in questo modo:

(commands 
(install 
    ;; do install 
) 

(uninstall 
    ;; do uninstall 
) 

;; ... 
) 

Ma dal momento che io non voglio installare e disinstallazione nel namespace globale , in qualche modo devo nella macro comandi, sostituire tutte le occorrenze dei comandi con forse ad esempio i nomi di prefisso, in questo modo:

(defmacro commands (&rest body) 
    (mapcar 
    (lambda (exp) 
    (setcar exp (intern (concat "package-" (symbol-name (car exp))))) 
    (setcdr exp (list (cons 'progn (cdr exp))))) 
    body) 
    `(progn ,@body)) 

(commands 
(install 
    ;; do install 
) 

(uninstall 
    ;; do uninstall 
) 

;; ... 
) 

Questo sembra un simile trucco. Inoltre, non funzionerà se ci sono comandi nidificati.

C'è qualche buona soluzione per questo o è hackerare la strada da percorrere?

Grazie!

+0

YASnipper prefixa le loro funzioni con 'yas /', quindi ottieni 'yas/expand' e così via. Non pensavo che fosse brutto. Ho adottato la convenzione per l'integrazione di tfs che ho scritto, quindi c'è 'tfs/checkout',' tfs/add', e così via. Questo sembra un modo facile e poco costoso per fare il nome scoping, in assenza di supporto formale per questo. – Cheeso

+0

Solo un'annotazione stilistica: non userei 'setcar' /' setcdr' come si fa nella definizione della macro 'command'. Crea un nuovo 'cons' (che renderebbe persino il codice più pulito). Non sai quali effetti potrebbe avere se il tuo macro espansore modifica arbitrariamente l'albero del codice originale in modo distruttivo. – Dirk

risposta

8

Come definire localmente install e gli amici? Questo non nasconderà le funzioni standard, ma non sembra che sia quello che cerchi davvero.

(defmacro commands (&rest body) 
    `(flet ((install (&rest args) (apply 'package-install args)) 
      (uninstall (&rest args) (apply 'package-uninstall args))) 
    ,@body)) 

Certo che ci si vuole generare quella lista di argomenti flet automaticamente. Hai bisogno di un elenco degli elementi del tuo pacchetto da qualche parte, possibilmente usando (feature-symbols 'package).

+1

Questo è esattamente quello che sto cercando! Molte grazie! – rejeep