Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emacs metaprogramming, dynamically define methods

I am trying to define some helper functions to quickly jump to different projects from within emacs. I started by defining a macro as follows

(defmacro project-alias (name path)
  `(defun ,name ()
     (interactive)
     (cd ,path)))

And this works great I can (project-alias foo "~/bar") no problem. The problem comes when I try and apply this macro over a list of tuples.

(setq projects '((foo . "~/foo")
                 (bar . "~/bar")))

(dolist (p projects)
  (project-alias (car p) (cdr p)))

The above code errors with

Debugger entered--Lisp error: (wrong-type-argument symbolp (car p))
  defalias((car p) (lambda nil (interactive) (cd (cdr p))))

I have tried passing the first argument in as a string and calling intern to get the symbol representation out with no joy, and I've also tried defining my macro to accept the string form and that doesn't work either

What am I doing wrong?

like image 764
eightbitraptor Avatar asked Feb 15 '23 18:02

eightbitraptor


2 Answers

If your use of the macro involves evaluating sexps to produce the name and path, then it needs to evaluate the sexps:

(defmacro project-alias (name path)
  `(defun ,(eval name) () (interactive) (cd ,(eval path))))

Alternatively, use a function:

(defun project-alias (name path)
  (eval `(defun ,name () (interactive) (cd ,path))))
like image 91
Drew Avatar answered Feb 23 '23 11:02

Drew


You could do either

(defun project-alias-f (name path)
  (eval `(defun ,name ()
       (interactive)
       (cd ,path))))



(dolist (p projects)
  (project-alias-f (car p) (cdr p)))

or

(dolist (p projects)
  (eval `(project-alias ,(car p) ,(cdr p))))
like image 43
Tobias Avatar answered Feb 23 '23 10:02

Tobias