2011-01-10 19 views
6

Chcę utworzyć DSL w Elisp patrząc coś takiego:Jak utworzyć DSL w Elisp

(install 
;; do install 
) 

(uninstall 
;; do uninstall 
) 

Jednak od Elisp posiada globalną przestrzeń nazw, to nie jest dobry pomysł. Przedrostek funkcji takich jak ten jest tak cholernie brzydki.

(package-install 
;; do install 
) 

(package-uninstall 
;; do uninstall 
) 

Pomyślałem więc jako kompromis wszystkie polecenia mogą być zapakowane w poleceniach nazwać tak:

(commands 
(install 
    ;; do install 
) 

(uninstall 
    ;; do uninstall 
) 

;; ... 
) 

Ale ponieważ nie chcę zainstalować i odinstaluj w globalnej przestrzeni nazw , Jakoś muszę w makrze poleceń, zamień wszystkie wystąpienia poleceń na przykład na prefiksy, na przykład:

(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 
) 

;; ... 
) 

To wygląda na taki hack. Plus to nie zadziała, jeśli istnieją jakieś zagnieżdżone polecenia.

Czy jest na to jakieś dobre rozwiązanie lub czy hakowanie może się udać?

Dzięki!

+0

YASnipper przedrostuje swoje funkcje za pomocą 'yas /', więc otrzymasz 'yas/expand' i tak dalej. Nie myślałem, że to było brzydkie. Przyjąłem konwencję dotyczącą integracji tfs, którą napisałem, więc istnieje 'tfs/checkout',' tfs/add', i tak dalej. Wydaje się, że jest to tani i łatwy sposób na przeprowadzanie scoringu nazw w przypadku braku formalnego wsparcia. – Cheeso

+0

Tylko adnotacja stylistyczna: Nie użyłbym 'setcar' /' setcdr' tak jak w definicji makra 'command'. Stwórz nowe "cons" (które sprawi, że kod będzie czystszy). Nie wiesz, jakie to może mieć skutki, jeśli twój ekspander makr dowolnie modyfikuje oryginalne drzewo kodu w niszczycielski sposób. – Dirk

Odpowiedz

8

Co powiesz na lokalną definicję install i znajomych? Nie ukryje to standardowych funkcji, ale wygląda na to, że naprawdę tak jest.

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

Oczywiście, że chcesz wygenerować tę listę flet argumentów automatycznie. Potrzebujesz gdzieś listy elementów paczki, prawdopodobnie używając (feature-symbols 'package).

+1

Dokładnie tego szukam! Wielkie dzięki! – rejeep