all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* defining many similar functions using macros
@ 2004-10-03  3:25 Joe Corneli
  2004-10-03  6:49 ` Daniel Pittman
  0 siblings, 1 reply; 6+ messages in thread
From: Joe Corneli @ 2004-10-03  3:25 UTC (permalink / raw)


I have a lot of functions that are very similar:

(defun tex-alpha ()
  (interactive)
  (insert "\\alpha"))

(defun tex-beta ()
  (interactive)
  (insert "\\beta"))

...

I would like to define them all in one go:

(dolist (elt '("alpha"
               "beta"
               ...))
  (define-tex-symbol elt))

This seems like a good chance to use a macro.  My first experiment
along these lines fails however, and I could use some help
re-designing it.

This macro works on single elements:

(defmacro define-tex-symbol (name)
  `(defun ,(intern (concat "tex-" name)) ()
     (interactive)
     (insert "\\" ,name)))

E.g. (define-tex-symbol "alpha") ;=> tex-alpha

But 

(dolist (elt '("alpha"
               "beta"))
  (define-tex-symbol elt))

triggers an error:

Debugger entered--Lisp error: (wrong-type-argument sequencep elt)
  concat("tex-" elt)
  (intern (concat "tex-" name))
  (list (quote defun) (intern (concat "tex-" name)) nil (quote (interactive)) (list (quote insert) "\\" name))
...

There seem to be some subtleties associated with macro expansion
that I'm missing here.  Help would be appreciated.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: defining many similar functions using macros
       [not found] <mailman.984.1096774354.2017.help-gnu-emacs@gnu.org>
@ 2004-10-03  5:31 ` Klaus Berndl
  2004-10-03  8:18 ` David Kastrup
  2004-10-04 15:55 ` Kevin Rodgers
  2 siblings, 0 replies; 6+ messages in thread
From: Klaus Berndl @ 2004-10-03  5:31 UTC (permalink / raw)


On Sat, 02 Oct 2004, Joe Corneli wrote:


[...]

>  This macro works on single elements:
>  
>  (defmacro define-tex-symbol (name)
>    `(defun ,(intern (concat "tex-" name)) ()
>       (interactive)
>       (insert "\\" ,name)))
>  
>  E.g. (define-tex-symbol "alpha") ;=> tex-alpha
>  
>  But 
>  
>  (dolist (elt '("alpha"
>                 "beta"))
>    (define-tex-symbol elt))
>  
>  triggers an error:
>  
>  Debugger entered--Lisp error: (wrong-type-argument sequencep elt)
>    concat("tex-" elt) (intern (concat "tex-" name)) (list (quote defun)
>    (intern (concat "tex-" name)) nil (quote (interactive)) (list (quote
>    insert) "\\" name))
>  ...
>  
>  There seem to be some subtleties associated with macro expansion
>  that I'm missing here.  Help would be appreciated.

Try:

(dolist (elt '("alpha"
               "beta"))
  (eval `(define-tex-symbol ,elt)))

Do not know if there are other and better solutions but this works!

Ciao,
Klaus

-- 
Klaus Berndl			mailto: klaus.berndl@sdm.de
sd&m AG				http://www.sdm.de
software design & management	
Carl-Wery-Str. 42, 81739 Muenchen, Germany
Tel +49 89 63812-392, Fax -220

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: defining many similar functions using macros
  2004-10-03  3:25 defining many similar functions using macros Joe Corneli
@ 2004-10-03  6:49 ` Daniel Pittman
  0 siblings, 0 replies; 6+ messages in thread
From: Daniel Pittman @ 2004-10-03  6:49 UTC (permalink / raw)


On 3 Oct 2004, Joe Corneli wrote:
> I have a lot of functions that are very similar:
>
> (defun tex-alpha ()
>   (interactive)
>   (insert "\\alpha"))
>
> (defun tex-beta ()
>   (interactive)
>   (insert "\\beta"))
>
> ...
>
> I would like to define them all in one go:

[...]

> This seems like a good chance to use a macro.  My first experiment
> along these lines fails however, and I could use some help
> re-designing it.
>
> This macro works on single elements:

[...]

> triggers an error:

[... when run from `dolist' ...]

> Debugger entered--Lisp error: (wrong-type-argument sequencep elt)
> concat("tex-" elt)
> (intern (concat "tex-" name))
> (list (quote defun) (intern (concat "tex-" name)) nil (quote (interactive))
> 	(list (quote insert) "\\" name))
> ...
>
> There seem to be some subtleties associated with macro expansion
> that I'm missing here.  Help would be appreciated.

Indeed.  The solution suggested elsewhere in the thread makes the macro
expansion work as expected, but why bother with that hoop - just write
the code directly:

(dolist (name '("alpha" "beta"))
  (fset (intern (concat "tex-" name))
        `(lambda () (interactive) (insert "\\" ,name))))

Note the backquote is needed to use the value of name, rather than the
symbol, but that cuts out the macro expansion middle-man nicely.

        Daniel
-- 
We live in a hallucination of our own devising.
        -- Alan Kay

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: defining many similar functions using macros
       [not found] <mailman.984.1096774354.2017.help-gnu-emacs@gnu.org>
  2004-10-03  5:31 ` Klaus Berndl
@ 2004-10-03  8:18 ` David Kastrup
  2004-10-04 15:55 ` Kevin Rodgers
  2 siblings, 0 replies; 6+ messages in thread
From: David Kastrup @ 2004-10-03  8:18 UTC (permalink / raw)


Joe Corneli <jcorneli@math.utexas.edu> writes:

> I have a lot of functions that are very similar:
>
> (defun tex-alpha ()
>   (interactive)
>   (insert "\\alpha"))
>
> (defun tex-beta ()
>   (interactive)
>   (insert "\\beta"))
>
> ...
>
> I would like to define them all in one go:
>
> (dolist (elt '("alpha"
>                "beta"
>                ...))
>   (define-tex-symbol elt))
>
> This seems like a good chance to use a macro.

Not really.

> My first experiment along these lines fails however, and I could use
> some help re-designing it.
>
> This macro works on single elements:
>
> (defmacro define-tex-symbol (name)
>   `(defun ,(intern (concat "tex-" name)) ()
>      (interactive)
>      (insert "\\" ,name)))
>
> E.g. (define-tex-symbol "alpha") ;=> tex-alpha
>
> But 
>
> (dolist (elt '("alpha"
>                "beta"))
>   (define-tex-symbol elt))
>
> triggers an error:
>
> Debugger entered--Lisp error: (wrong-type-argument sequencep elt)
>   concat("tex-" elt)
>   (intern (concat "tex-" name))
>   (list (quote defun) (intern (concat "tex-" name)) nil (quote (interactive)) (list (quote insert) "\\" name))
> ...
>
> There seem to be some subtleties associated with macro expansion
> that I'm missing here.

Nothing subtle here at all. macros are substitutions at compile time
(that's why they are efficient).  So the "intern" gets evaluated at
compile time.  At that time, `name' is bound to the unevaled symbol
`elt'.  So what defun would you expect to result from your code?
Really.  Take pencil and paper and write down the expansion you wanted
to occur.  You can't calculate the symbol to define at compile time,
because it is supposed to be a different one each time through the
loop.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: defining many similar functions using macros
       [not found] <mailman.984.1096774354.2017.help-gnu-emacs@gnu.org>
  2004-10-03  5:31 ` Klaus Berndl
  2004-10-03  8:18 ` David Kastrup
@ 2004-10-04 15:55 ` Kevin Rodgers
  2004-10-04 16:30   ` David Kastrup
  2 siblings, 1 reply; 6+ messages in thread
From: Kevin Rodgers @ 2004-10-04 15:55 UTC (permalink / raw)


Joe Corneli wrote:
 > I would like to define them all in one go:
 >
 > (dolist (elt '("alpha"
 >                "beta"
 >                ...))
 >   (define-tex-symbol elt))
 >
 > This seems like a good chance to use a macro.  My first experiment
 > along these lines fails however, and I could use some help
 > re-designing it.
 >
 > This macro works on single elements:
 >
 > (defmacro define-tex-symbol (name)
 >   `(defun ,(intern (concat "tex-" name)) ()
 >      (interactive)
 >      (insert "\\" ,name)))
 >
 > E.g. (define-tex-symbol "alpha") ;=> tex-alpha
 >
 > But
 >
 > (dolist (elt '("alpha"
 >                "beta"))
 >   (define-tex-symbol elt))

[M-x rhetorical] Why is that better than:

(define-text-symbol "alpha")
(define-text-symbol "beta")

 > triggers an error:
 >
 > Debugger entered--Lisp error: (wrong-type-argument sequencep elt)
 >   concat("tex-" elt)
 >   (intern (concat "tex-" name))
 >   (list (quote defun) (intern (concat "tex-" name)) nil (quote (interactive)) (list (quote insert) "\\" name))
 > ...
 >
 > There seem to be some subtleties associated with macro expansion
 > that I'm missing here.  Help would be appreciated.

The macro argument NAME is bound to the unevaluated form the macro is
called with, e.g. "alpha".  If you want to be able to call the macro
with some other kind of form that must be evaluated to yield a string,
you have to write your macro to take that into account.

In Lisp, a macro transforms one expression into another, which is then
evaluated.  The backquote syntax makes it easy to specify the output
expression, and the comma syntax allows you to substitute forms
evaluated at compile-time for literal forms.  But then the resulting
expression still has to be evaluated.

A problem arises when you want to generate a call to another macro (e.g.
defun) that requires an unevaluated form (i.e. the function name symbol)
that you compute dynamically.  That's why you have to put the comma
before the  (intern ...) form: because this is valid

	(defun tex-alpha ...)

but this isn't

	(defun (intern (concat "tex-" "alpha")) ...)

As someone else pointed out, the solution is to use the fset function
instead of the macro:

(defmacro define-tex-symbol (name)
   `(fset (intern (concat "tex-" ,name))
          (lambda ()
            (interactive)
            (insert "\\" ,name))))

-- 
Kevin Rodgers

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: defining many similar functions using macros
  2004-10-04 15:55 ` Kevin Rodgers
@ 2004-10-04 16:30   ` David Kastrup
  0 siblings, 0 replies; 6+ messages in thread
From: David Kastrup @ 2004-10-04 16:30 UTC (permalink / raw)


Kevin Rodgers <ihs_4664@yahoo.com> writes:

> As someone else pointed out, the solution is to use the fset function
> instead of the macro:
>
> (defmacro define-tex-symbol (name)
>    `(fset (intern (concat "tex-" ,name))
>           (lambda ()
>             (interactive)
>             (insert "\\" ,name))))

It is completely pointless to use a macro here.  The only effect you
gain by it is side effects from multiple evaluation of `name'.  Just
use defun here: you can't hope to gain much efficiency from avoiding
just such a tiny bit of expansion in an otherwise complicated
operation.

To wit:
(defun define-tex-symbol (name)
   (fset (intern (concat "tex-" name))
         `(lambda () (interactive)
            (insert "\\" ,name))))

If you really want the "optimization", use defsubst instead of defun.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-10-04 16:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-03  3:25 defining many similar functions using macros Joe Corneli
2004-10-03  6:49 ` Daniel Pittman
     [not found] <mailman.984.1096774354.2017.help-gnu-emacs@gnu.org>
2004-10-03  5:31 ` Klaus Berndl
2004-10-03  8:18 ` David Kastrup
2004-10-04 15:55 ` Kevin Rodgers
2004-10-04 16:30   ` David Kastrup

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.