Pracuję nad optymalizacją konfiguracji emacsa, w której mogę dynamicznie tworzyć interaktywne funkcje dla wszystkich motywów, które mam na liście.
Poniżej znajduje się uproszczona wersja konstruktu, który próbuję wykonać.
;; List containing names of functions that I want to create
(setq my/defun-list '(zz-abc
zz-def
zz-ghi))
;; Elisp macro to create an interactive defun whose name
;; is passed as the macro argument
(defmacro my/create-defun (defun-name)
`(defun ,defun-name ()
(interactive)
(let ((fn-name (symbol-name ',defun-name)))
(message "Testing creation of function %s" fn-name))))
;; Loop to call the above macro for each element in the list
;; DOES *NOT* WORK
(dolist (name my/defun-list)
(my/create-defun name))
Ale jeśli rozwinę pętlę ręcznie, zadziała:
;; WORKS
(my/create-defun zz-abc)
(my/create-defun zz-def)
(my/create-defun zz-ghi)
Ale poniżej nie działa, gdy przekazuję nazwy symboli (co prawdopodobnie dzieje się, gdy pętla sama się rozwija). Zwróć uwagę na cudzysłowy przed argumentami makr.
;; DOES *NOT* WORK
(my/create-defun 'zz-abc)
(my/create-defun 'zz-def)
(my/create-defun 'zz-ghi)
Aktualizacja
Dzięki pomocy @wvxvw w końcu udało mi się to uruchomić !
Jak sugeruje @wvxvw, nie będę generować partii generujących odrzucenia dla każdego przypadku użycia. To był szczególny przypadek użycia, w którym dla motywu o nazwie XYZ
chcę wygenerować wywołanie defun, load-theme/XYZ
które działa
- Wyłączanie wszystkich innych motywów, które mogą być aktywne
- wywołanie
load-theme
dlaXYZ
- Robienie niestandardowych rzeczy związanych z tym tematem; Przechodzę przez niestandardowe ustawienia dla każdego motywu
my/themes
.
elisp-macros
Kaushal Modi
źródło
źródło
defuns
środkuprogn
.progn
może być formularzem najwyższego poziomu (w tym sensie, że wszystko, co dotyczy formularzy najwyższego poziomu, dotyczy również treściprogn
). Chciałbym jednak zakwestionować uzasadnienie tworzenia funkcji w taki sposób: dlaczego nie mieć, powiedzmy, tabelę z lambdami jako wartościami?cons
e, ale planuję przekonwertować je na listy z niestandardowymi właściwościami dla każdego motywu.(my/create-defun name)
3 razy, więc powinieneś zdefiniować funkcję o nazwiename
3 razy.Odpowiedzi:
Oto próba wyjaśnienia i kilka sugestii.
Teraz spróbujmy to naprawić:
Przykład z odczytaniem nazw funkcji ze zmiennej
Problem miał charakter koncepcyjny: makra służą do generowania kodu, gdy środowisko chce go odczytać. Kiedy wykonujesz kod sam (jako użytkownik twojego programu), jest już za późno, aby to zrobić (środowisko powinno wiedzieć, co to jest program).
Uwaga marginalna: odradzałbym łączenie kilku
defuns
. Powodem jest to, że sprawia, że debugowanie jest o wiele bardziej skomplikowane. Mała nadmiarowość, którą masz w powtarzanych definicjach, bardzo dobrze się opłaca w fazie konserwacji (a konserwacja jest zazwyczaj najdłuższą fazą w czasie trwania programu).źródło
mapcar
wymyślę użycie z alistami. To nie wydaje się działać z moim faktycznym przypadkiem użycia. Zagłębię się w to tak szybko, jak to możliwe.(mapcar (lambda (x) (message "argument: %s" x)) some-alist)
aby zobaczyć, jaki jest argument, i pracować od tego momentu. Jeśli to lista asocjacyjne, to bym sobie wyobrazić wyjście do być coś podobnegoargument: (foo . bar)
, a następnie yo może uzyskać dostępfoo
za pomocącar
ibar
przy użyciucdr
funkcji.nth
fn zamiastcar
icadr
), alesequencep
zameldowałem sięmapcar
błędnie. Jako dane wejściowe podawałem alist, ale mapcar nie sądził, że to sekwencja. Jeśli tak(sequencep my-alist)
, to nie jest zero. Więc jestem zdezorientowany .. Muszę to jeszcze debugować.my-alist
byłnil
lub zapomniałeś (lub dodany dodatkowy) cytaty, tak abymy-alist
był albo symbol, lub oceniano jeszcze być coś innego. Prawdopodobnie chcesz rozszerzyć swoje pytanie o nowy kod, aby ułatwić udzielenie odpowiedzi.Niezupełnie odrzuca, ale dlaczego nie? : P
źródło
Mam w swoim init:
Jest to być może nieco bardziej skomplikowane niż potrzeba (szczególnie ta dodatkowa ewaluacja), ale pozwala mi generować wyrzuty potrzebne dla tych właściwości (i zawierać ciągi znaków z poprawnymi informacjami).
źródło