From: Lowell Kirsh
Subject: elisp macros problem
Date: 
Message-ID: <cduad9$7tg$1@mughi.cs.ubc.ca>
I am defining an emacs lisp macro to do:

(my-add-hook 'lisp
    ...)

which should give:

(add-hook 'lisp-mode-hook
   (lambda () ...))

I have:

(defmacro my-add-hook (hook &rest body)
   (let ((tempvar (make-symbol "cat")))
     `(flet ((,tempvar (sym str)
                       (make-symbol (concat (symbol-name sym) str))))
        (add-hook (cat ,hook "-mode-hook") (lambda () ,@body)))))

Does anyone know what's wrong with this and why it doesn't work?

Lowell

From: Barry Margolin
Subject: Re: elisp macros problem
Date: 
Message-ID: <barmar-2EE74B.15152724072004@comcast.dca.giganews.com>
In article <············@mughi.cs.ubc.ca>,
 Lowell Kirsh <······@cs.ubc.ca> wrote:

> I am defining an emacs lisp macro to do:
> 
> (my-add-hook 'lisp
>     ...)
> 
> which should give:
> 
> (add-hook 'lisp-mode-hook
>    (lambda () ...))
> 
> I have:
> 
> (defmacro my-add-hook (hook &rest body)
>    (let ((tempvar (make-symbol "cat")))
>      `(flet ((,tempvar (sym str)
>                        (make-symbol (concat (symbol-name sym) str))))
>         (add-hook (cat ,hook "-mode-hook") (lambda () ,@body)))))
> 
> Does anyone know what's wrong with this and why it doesn't work?

You need to use ,tempvar in place of cat in the last line.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Pascal Bourguignon
Subject: Re: elisp macros problem
Date: 
Message-ID: <873c3h41o6.fsf@thalassa.informatimago.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <············@mughi.cs.ubc.ca>,
>  Lowell Kirsh <······@cs.ubc.ca> wrote:
> 
> > I am defining an emacs lisp macro to do:
> > 
> > (my-add-hook 'lisp
> >     ...)
> > 
> > which should give:
> > 
> > (add-hook 'lisp-mode-hook
> >    (lambda () ...))
> > 
> > I have:
> > 
> > (defmacro my-add-hook (hook &rest body)
> >    (let ((tempvar (make-symbol "cat")))
> >      `(flet ((,tempvar (sym str)
> >                        (make-symbol (concat (symbol-name sym) str))))
> >         (add-hook (cat ,hook "-mode-hook") (lambda () ,@body)))))
> > 
> > Does anyone know what's wrong with this and why it doesn't work?
> 
> You need to use ,tempvar in place of cat in the last line.

Then, (not (eq (make-symbol "toto")(make-symbol "toto"))), even on emacs lisp.
You should use intern!


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: David Kastrup
Subject: Re: elisp macros problem
Date: 
Message-ID: <x5hdrxdt9x.fsf@lola.goethe.zz>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> Barry Margolin <······@alum.mit.edu> writes:
> 
> > In article <············@mughi.cs.ubc.ca>,
> >  Lowell Kirsh <······@cs.ubc.ca> wrote:
> > 
> > > (defmacro my-add-hook (hook &rest body)
> > >    (let ((tempvar (make-symbol "cat")))
> > >      `(flet ((,tempvar (sym str)
> > >                        (make-symbol (concat (symbol-name sym) str))))
> > >         (add-hook (cat ,hook "-mode-hook") (lambda () ,@body)))))
> > > 
> > > Does anyone know what's wrong with this and why it doesn't work?
> > 
> > You need to use ,tempvar in place of cat in the last line.
> 
> Then, (not (eq (make-symbol "toto")(make-symbol "toto"))), even on
> emacs lisp.  You should use intern!

For accessing xxx-mode-hook, yes.  But for the "cat" thingy, ,tempvar
would be ok, even though pretty pointless: one does not really need to
bind a function here.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <4102D97E.6080902@cs.ubc.ca>
Thanks all. I now see how pointless cat was, but the reason it was there 
in the first place was because i had made it a separate function (for 
testing).

cheers,
Lowell

David Kastrup wrote:
> Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> 
> 
>>Barry Margolin <······@alum.mit.edu> writes:
>>
>>
>>>In article <············@mughi.cs.ubc.ca>,
>>> Lowell Kirsh <······@cs.ubc.ca> wrote:
>>>
>>>
>>>>(defmacro my-add-hook (hook &rest body)
>>>>   (let ((tempvar (make-symbol "cat")))
>>>>     `(flet ((,tempvar (sym str)
>>>>                       (make-symbol (concat (symbol-name sym) str))))
>>>>        (add-hook (cat ,hook "-mode-hook") (lambda () ,@body)))))
>>>>
>>>>Does anyone know what's wrong with this and why it doesn't work?
>>>
>>>You need to use ,tempvar in place of cat in the last line.
>>
>>Then, (not (eq (make-symbol "toto")(make-symbol "toto"))), even on
>>emacs lisp.  You should use intern!
> 
> 
> For accessing xxx-mode-hook, yes.  But for the "cat" thingy, ,tempvar
> would be ok, even though pretty pointless: one does not really need to
> bind a function here.
> 
From: David Kastrup
Subject: Re: elisp macros problem
Date: 
Message-ID: <x5n01pdydq.fsf@lola.goethe.zz>
Lowell Kirsh <······@cs.ubc.ca> writes:

> I am defining an emacs lisp macro to do:
> 
> (my-add-hook 'lisp
>     ...)
> 
> which should give:
> 
> (add-hook 'lisp-mode-hook
>    (lambda () ...))
> 
> I have:
> 
> (defmacro my-add-hook (hook &rest body)
>    (let ((tempvar (make-symbol "cat")))
>      `(flet ((,tempvar (sym str)
>                        (make-symbol (concat (symbol-name sym) str))))
>         (add-hook (cat ,hook "-mode-hook") (lambda () ,@body)))))
> 
> Does anyone know what's wrong with this and why it doesn't work?

I don't know where to start...

First of all, your use of flet is complete nonsense.  You flet an
uninterned symbol with the name "cat" to some function.  However, you
never use that function.  Instead you are trying to call the interned
symbol "cat" (which is probably undefined).  Even if one fixed that,
it is completely unnecessary.  Just do

(defmacro my-add-hook (hook &rest body)
  `(add-hook ',(intern (concat (symbol-name hook) "-mode-hook"))
        (lambda () ,@body)))

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <4102DDB8.7070806@cs.ubc.ca>
> (defmacro my-add-hook (hook &rest body)
>   `(add-hook ',(intern (concat (symbol-name hook) "-mode-hook"))
>         (lambda () ,@body)))
> 

I just tried it out and it doesn't seem to work. I tried both:

(my-add-hook 'emacs-lisp (keyboard-translate ?\( ?\[))
              ^
and

(my-add-hook emacs-lisp (keyboard-translate ?\( ?\[))


Lowell
From: ······@cs.ubc.ca
Subject: cancel <················@cs.ubc.ca>
Date: 
Message-ID: <cdumko$aqj$2@mughi.cs.ubc.ca>
This message was cancelled from within Mozilla.
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <4102DDEE.9080906@cs.ubc.ca>
 > (defmacro my-add-hook (hook &rest body)
 >   `(add-hook ',(intern (concat (symbol-name hook) "-mode-hook"))
 >         (lambda () ,@body)))
 >

I just tried it out and it doesn't seem to work. I tried both:

(my-add-hook 'emacs-lisp (keyboard-translate ?\( ?\[))
              ^
and

(my-add-hook emacs-lisp (keyboard-translate ?\( ?\[))


Lowell
From: David Kastrup
Subject: Re: elisp macros problem
Date: 
Message-ID: <x5zn5pc6s7.fsf@lola.goethe.zz>
Please don't copy me with Email to Usenet articles: it is a very bad
breach of netiquette to force the unwary to reply twice, once in
private and then again in public.

Lowell Kirsh <······@cs.ubc.ca> writes:

>  > (defmacro my-add-hook (hook &rest body)
>  >   `(add-hook ',(intern (concat (symbol-name hook) "-mode-hook"))
>  >         (lambda () ,@body)))
>  >
> 
> I just tried it out and it doesn't seem to work. I tried both:
> 
> (my-add-hook 'emacs-lisp (keyboard-translate ?\( ?\[))
>               ^

Which is wrong.

> and
> 
> (my-add-hook emacs-lisp (keyboard-translate ?\( ?\[))

Which results here in:

emacs-lisp-mode-hook's value is 
((lambda nil
   (keyboard-translate 40 91)))


Hook run when entering Emacs Lisp mode.

You can customize this variable.

Defined in `emacs-lisp/lisp-mode'.

[back]

Looks fine to me.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <cdv446$e1i$1@mughi.cs.ubc.ca>
sorry bout the bad etiquette. also, it turns out that it does seem to 
work. the reason that i didn't realize it was working was that i thought 
you could (add-hook 'some-mode ...) more than once, but really, this 
will just overwrite the previously added hook.

lowell

David Kastrup wrote:
> Please don't copy me with Email to Usenet articles: it is a very bad
> breach of netiquette to force the unwary to reply twice, once in
> private and then again in public.
> 
> Lowell Kirsh <······@cs.ubc.ca> writes:
> 
> 
>> > (defmacro my-add-hook (hook &rest body)
>> >   `(add-hook ',(intern (concat (symbol-name hook) "-mode-hook"))
>> >         (lambda () ,@body)))
>> >
>>
>>I just tried it out and it doesn't seem to work. I tried both:
>>
>>(my-add-hook 'emacs-lisp (keyboard-translate ?\( ?\[))
>>              ^
> 
> 
> Which is wrong.
> 
> 
>>and
>>
>>(my-add-hook emacs-lisp (keyboard-translate ?\( ?\[))
> 
> 
> Which results here in:
> 
> emacs-lisp-mode-hook's value is 
> ((lambda nil
>    (keyboard-translate 40 91)))
> 
> 
> Hook run when entering Emacs Lisp mode.
> 
> You can customize this variable.
> 
> Defined in `emacs-lisp/lisp-mode'.
> 
> [back]
> 
> Looks fine to me.
> 
From: Kalle Olavi Niemitalo
Subject: Re: elisp macros problem
Date: 
Message-ID: <87fz7g4ajw.fsf@Astalo.kon.iki.fi>
Lowell Kirsh <······@cs.ubc.ca> writes:

> the reason that i didn't realize it was working was that i
> thought you could (add-hook 'some-mode ...) more than once, but
> really, this will just overwrite the previously added hook.

No, it won't.

(setq sample-hook '())
(add-hook 'sample-hook 'sample-1)
(add-hook 'sample-hook 'sample-2)
(add-hook 'sample-hook 'sample-2)

After these forms, the value of sample-hook is (sample-2 sample-1).
The second add-hook did not overwrite the first one.
However, the third one had no effect, because sample-2 was
already in the hook.
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce1n4n$2gt$1@mughi.cs.ubc.ca>
Why does this not work:

(defmacro my-add-hooks (hooks &rest body)
   `(dolist (hook ,hooks)
       (my-add-hook hook ,@body)))

??

Lowell

Lowell Kirsh wrote:
> I am defining an emacs lisp macro to do:
> 
> (my-add-hook 'lisp
>    ...)
> 
> which should give:
> 
> (add-hook 'lisp-mode-hook
>   (lambda () ...))
> 
> I have:
> 
> (defmacro my-add-hook (hook &rest body)
>   (let ((tempvar (make-symbol "cat")))
>     `(flet ((,tempvar (sym str)
>                       (make-symbol (concat (symbol-name sym) str))))
>        (add-hook (cat ,hook "-mode-hook") (lambda () ,@body)))))
> 
> Does anyone know what's wrong with this and why it doesn't work?
> 
> Lowell
From: Rahul Jain
Subject: Re: elisp macros problem
Date: 
Message-ID: <877jsrsfa0.fsf@nyct.net>
Lowell Kirsh <······@cs.ubc.ca> writes:

> Why does this not work:
>
> (defmacro my-add-hooks (hooks &rest body)
>    `(dolist (hook ,hooks)
>        (my-add-hook hook ,@body)))
>
> ??

It does. In fact, every possible string of characters works as it's
supposed to.

You probably mean "why does this not do X?" but you never tell us what X
is, so we don't know how to help you achieve that.

Hint: you might want to macroexpand-1 a sample usage of the macro and
see if it expands to what you desired.

According to your definition:
(my-add-hooks '(lisp-mode-hook emacs-lisp-mode-hook)
  ...)
<=>
(dolist (hook '(lisp-mode-hook emacs-lisp-mode-hook))
  (my-add-hook hook ...))

Is that what you wanted?

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce1rnb$3kd$1@mughi.cs.ubc.ca>
Rahul Jain wrote:
> You probably mean "why does this not do X?" but you never tell us what X
> is, so we don't know how to help you achieve that.

What I meant was why does this not do the obvoious thing I want it to do...

> Hint: you might want to macroexpand-1 a sample usage of the macro and
> see if it expands to what you desired.
> 
> According to your definition:
> (my-add-hooks '(lisp-mode-hook emacs-lisp-mode-hook)
>   ...)
> <=>
> (dolist (hook '(lisp-mode-hook emacs-lisp-mode-hook))
>   (my-add-hook hook ...))
> 
> Is that what you wanted?

Almost. The call should actually be

(my-add-hooks '(lisp emacs-lisp)
    ...)

And yes, that is what I wanted.

Lowell
From: Pascal Bourguignon
Subject: Re: elisp macros problem
Date: 
Message-ID: <87ekmz2z2o.fsf@thalassa.informatimago.com>
Lowell Kirsh <······@cs.ubc.ca> writes:

> Rahul Jain wrote:
> > You probably mean "why does this not do X?" but you never tell us what X
> > is, so we don't know how to help you achieve that.
> 
> What I meant was why does this not do the obvoious thing I want it to do...

Perhaps because telepathic computers have not been invented yet?

Erase that. Perhaps because telepathic computers are not on the shelf items 
yet, and you don't work for the US Air Force, therefore you don't have one?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce20cu$4n7$1@mughi.cs.ubc.ca>
ok, ok. it seemed obvious to me but i guess it wasn't. i concede.

Pascal Bourguignon wrote:

> Lowell Kirsh <······@cs.ubc.ca> writes:
> 
> 
>>Rahul Jain wrote:
>>
>>>You probably mean "why does this not do X?" but you never tell us what X
>>>is, so we don't know how to help you achieve that.
>>
>>What I meant was why does this not do the obvoious thing I want it to do...
> 
> 
> Perhaps because telepathic computers have not been invented yet?
> 
> Erase that. Perhaps because telepathic computers are not on the shelf items 
> yet, and you don't work for the US Air Force, therefore you don't have one?
> 
> 
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce1rpm$3kd$2@mughi.cs.ubc.ca>
btw, I can't find macroexpand-1. Does it exist in elisp?

Rahul Jain wrote:
> Lowell Kirsh <······@cs.ubc.ca> writes:
> 
> 
>>Why does this not work:
>>
>>(defmacro my-add-hooks (hooks &rest body)
>>   `(dolist (hook ,hooks)
>>       (my-add-hook hook ,@body)))
>>
>>??
> 
> 
> It does. In fact, every possible string of characters works as it's
> supposed to.
> 
> You probably mean "why does this not do X?" but you never tell us what X
> is, so we don't know how to help you achieve that.
> 
> Hint: you might want to macroexpand-1 a sample usage of the macro and
> see if it expands to what you desired.
> 
> According to your definition:
> (my-add-hooks '(lisp-mode-hook emacs-lisp-mode-hook)
>   ...)
> <=>
> (dolist (hook '(lisp-mode-hook emacs-lisp-mode-hook))
>   (my-add-hook hook ...))
> 
> Is that what you wanted?
> 
From: Kevin Rodgers
Subject: Re: elisp macros problem
Date: 
Message-ID: <41058C78.7030806@yahoo.com>
[Please don't top-post.]

Lowell Kirsh wrote:
 > btw, I can't find macroexpand-1. Does it exist in elisp?

Just use macroexpand.

-- 
Kevin Rodgers
From: Kalle Olavi Niemitalo
Subject: Re: elisp macros problem
Date: 
Message-ID: <877jsq4dp4.fsf@Astalo.kon.iki.fi>
Lowell Kirsh <······@cs.ubc.ca> writes:

> btw, I can't find macroexpand-1. Does it exist in elisp?

No, it doesn't.  It can be implemented in elisp but not easily.
There are several tricky cases, such as autoloaded macros, or
global aliases that refer to lexical macros.

http://paste.lisp.org/display/1684
From: Barry Margolin
Subject: Re: elisp macros problem
Date: 
Message-ID: <barmar-D0F915.22035425072004@comcast.dca.giganews.com>
In article <············@mughi.cs.ubc.ca>,
 Lowell Kirsh <······@cs.ubc.ca> wrote:

> Why does this not work:
> 
> (defmacro my-add-hooks (hooks &rest body)
>    `(dolist (hook ,hooks)
>        (my-add-hook hook ,@body)))
> 
> ??

It looks like it should work to me.  Make sure you quote the list of 
hooks when calling it, e.g.

(my-add-hooks '(emacs-lisp lisp) (local-set-key ...))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce1sfo$3ol$1@mughi.cs.ubc.ca>
Yes, I have been making sure to quote the list, but it doesn't seem to 
work at all. I've also tried to macroexpand the forms I'm evaluating but 
the minibuffer just shows a condensed version of the expansion with lots 
of '...' placeholders. Is there a simple way to macroexpand and pretty 
print a form without the '...'s ?

Lowell

Barry Margolin wrote:
> In article <············@mughi.cs.ubc.ca>,
>  Lowell Kirsh <······@cs.ubc.ca> wrote:
> 
> 
>>Why does this not work:
>>
>>(defmacro my-add-hooks (hooks &rest body)
>>   `(dolist (hook ,hooks)
>>       (my-add-hook hook ,@body)))
>>
>>??
> 
> 
> It looks like it should work to me.  Make sure you quote the list of 
> hooks when calling it, e.g.
> 
> (my-add-hooks '(emacs-lisp lisp) (local-set-key ...))
> 
From: Barry Margolin
Subject: Re: elisp macros problem
Date: 
Message-ID: <barmar-D2BD3E.00492626072004@comcast.dca.giganews.com>
In article <············@mughi.cs.ubc.ca>,
 Lowell Kirsh <······@cs.ubc.ca> wrote:

> Yes, I have been making sure to quote the list, but it doesn't seem to 
> work at all. I've also tried to macroexpand the forms I'm evaluating but 
> the minibuffer just shows a condensed version of the expansion with lots 
> of '...' placeholders. Is there a simple way to macroexpand and pretty 
> print a form without the '...'s ?

Use the *scratch* buffer for a better interface to the Emacs Lisp R-E-P 
loop.

> 
> Lowell
> 
> Barry Margolin wrote:
> > In article <············@mughi.cs.ubc.ca>,
> >  Lowell Kirsh <······@cs.ubc.ca> wrote:
> > 
> > 
> >>Why does this not work:
> >>
> >>(defmacro my-add-hooks (hooks &rest body)
> >>   `(dolist (hook ,hooks)
> >>       (my-add-hook hook ,@body)))
> >>
> >>??
> > 
> > 
> > It looks like it should work to me.  Make sure you quote the list of 
> > hooks when calling it, e.g.
> > 
> > (my-add-hooks '(emacs-lisp lisp) (local-set-key ...))
> >

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Pascal Bourguignon
Subject: Re: elisp macros problem
Date: 
Message-ID: <87acxn2vkp.fsf@thalassa.informatimago.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <············@mughi.cs.ubc.ca>,
>  Lowell Kirsh <······@cs.ubc.ca> wrote:
> 
> > Yes, I have been making sure to quote the list, but it doesn't seem to 
> > work at all. I've also tried to macroexpand the forms I'm evaluating but 
> > the minibuffer just shows a condensed version of the expansion with lots 
> > of '...' placeholders. Is there a simple way to macroexpand and pretty 
> > print a form without the '...'s ?
> 
> Use the *scratch* buffer for a better interface to the Emacs Lisp R-E-P 
> loop.

Or any elisp buffer, with: C-u C-x C-e:

(macroexpand '(push 'a a)) C-u C-x C-e --> (setq a (cons (quote a) a))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Oliver Scholz
Subject: Re: elisp macros problem
Date: 
Message-ID: <u7jsrmh7i.fsf@ID-87814.user.uni-berlin.de>
Lowell Kirsh <······@cs.ubc.ca> writes:

[...]
> Is there a simple way to macroexpand and pretty print a form without
> the '...'s ?
[...]

I use M-x ielm for that.

    Oliver
-- 
9 Thermidor an 212 de la Révolution
Liberté, Egalité, Fraternité!
From: David Kastrup
Subject: Re: elisp macros problem
Date: 
Message-ID: <x5k6wr48ja.fsf@lola.goethe.zz>
Lowell Kirsh <······@cs.ubc.ca> writes:

> Why does this not work:
> 
> (defmacro my-add-hooks (hooks &rest body)
>    `(dolist (hook ,hooks)
>        (my-add-hook hook ,@body)))
> 
> ??

Because you need to write
`(dolist (hook ',hooks)

and then call this with an _unquoted_ list, like
(my-add-hooks (lisp emacs-lisp)
  body)

Apart from that, I consider this sort of thing a crock.  What are you
hoping to achieve that you would not be better off doing by a proper
function instead of a macro?

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce4t9b$otm$1@mughi.cs.ubc.ca>
A crock? Now that I've got that macrology out of the way, does not

(my-add-hooks (emacs-lisp lisp lisp-interaction)
   (fun foo))

look better than

(add-hook 'emacs-lisp-mode-hook
    (lambda () (fun foo)))

(add-hook 'lisp-mode-hook
    (lambda () (fun foo)))

(add-hook ....


I think it does :)

Lowell

David Kastrup wrote:

> Lowell Kirsh <······@cs.ubc.ca> writes:
> 
> 
>>Why does this not work:
>>
>>(defmacro my-add-hooks (hooks &rest body)
>>   `(dolist (hook ,hooks)
>>       (my-add-hook hook ,@body)))
>>
>>??
> 
> 
> Because you need to write
> `(dolist (hook ',hooks)
> 
> and then call this with an _unquoted_ list, like
> (my-add-hooks (lisp emacs-lisp)
>   body)
> 
> Apart from that, I consider this sort of thing a crock.  What are you
> hoping to achieve that you would not be better off doing by a proper
> function instead of a macro?
> 
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce4u7l$p63$1@mughi.cs.ubc.ca>
This still doesn't seem to work. With the following defun and call:

(defmacro my-add-hooks (hooks &rest body)
   `(dolist (hook ',hooks)
      (my-add-hook hook ,@body)))

(my-add-hooks (inferior-lisp lisp emacs-lisp lisp-interaction)
               (imenu-add-to-menubar "Symbols"))

I get the following macroexpansion, which looks correct to me, but 
doesn't actually do anything:

(cl-block-wrapper
  (catch (quote --cl-block-nil--)
    (let ((--dolist-temp--20870 (quote (inferior-lisp lisp emacs-lisp 
lisp-interaction)))
          hook)
      (while --dolist-temp--20870
        (setq hook (car --dolist-temp--20870))
        (my-add-hook hook
                     (imenu-add-to-menubar "Symbols"))
        (setq --dolist-temp--20870 (cdr --dolist-temp--20870)))
      nil)))


Lowell


David Kastrup wrote:

> Lowell Kirsh <······@cs.ubc.ca> writes:
> 
> 
>>Why does this not work:
>>
>>(defmacro my-add-hooks (hooks &rest body)
>>   `(dolist (hook ,hooks)
>>       (my-add-hook hook ,@body)))
>>
>>??
> 
> 
> Because you need to write
> `(dolist (hook ',hooks)
> 
> and then call this with an _unquoted_ list, like
> (my-add-hooks (lisp emacs-lisp)
>   body)
> 
> Apart from that, I consider this sort of thing a crock.  What are you
> hoping to achieve that you would not be better off doing by a proper
> function instead of a macro?
> 
From: David Kastrup
Subject: Re: elisp macros problem
Date: 
Message-ID: <x5zn5lvs43.fsf@lola.goethe.zz>
Lowell Kirsh <······@cs.ubc.ca> writes:

> This still doesn't seem to work. With the following defun and call:
> 
> (defmacro my-add-hooks (hooks &rest body)
>    `(dolist (hook ',hooks)
>       (my-add-hook hook ,@body)))
> 
> (my-add-hooks (inferior-lisp lisp emacs-lisp lisp-interaction)
>                (imenu-add-to-menubar "Symbols"))
> 
> I get the following macroexpansion, which looks correct to me, but
> doesn't actually do anything:
> 
> (cl-block-wrapper
>   (catch (quote --cl-block-nil--)
>     (let ((--dolist-temp--20870 (quote (inferior-lisp lisp emacs-lisp
>     lisp-interaction)))
>           hook)
>       (while --dolist-temp--20870
>         (setq hook (car --dolist-temp--20870))
>         (my-add-hook hook
>                      (imenu-add-to-menubar "Symbols"))
>         (setq --dolist-temp--20870 (cdr --dolist-temp--20870)))
>       nil)))

That's because my-add-hook is a macro, too, and so you just add stuff
to hook-mode-hook three times.

> > Apart from that, I consider this sort of thing a crock.  What are
> > you hoping to achieve that you would not be better off doing by a
> > proper function instead of a macro?

In short, I still consider this sort of thing a crock, since you'd be
better off using a function instead of a macro.  You are unable to
comprehend what your macros do, and it shows.  Macros are just not
sensible for this sort of thing.  Use functions instead.  You'll need
to use some quotes at the outer level, but you'll understand what
happens.

To fix the above, you'd need to write something like

(defmacro my-add-hooks (hooks &rest body)
   (dolist (hook hooks)
      `(my-add-hook ,hook ,@body)))


-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ce52me$q1m$1@mughi.cs.ubc.ca>
Hmmm, I was only trying to use macros because I thought what I was 
trying wasn't possible with functions. Would this be a more appropriate 
approach?

(defun my-add-hook (hook &rest body)
   (add-hook (intern (concat (symbol-name hook) "-mode-hook"))
             `(lambda () ,@body)))

and then call it like:

(my-add-hook 'lisp-interaction
              '(my-translate-paren-types)
              '(imenu-add-to-menubar "Symbols")
              )

This seems a little more verbose with all the quotes, but I guess it 
could be the 'better' approach since it avoids using macros.

Perhaps my macro approach was a crock. The only reason I defended it was 
becuase I thought you meant that creating the my-add-hook functionality 
itself was the crock.

Well, I'm going with functions now, and I'm also going to get back to 
reading Paul Graham's 'On Lisp', the only comprehensive lisp macros book 
I know of (are there others?)

Lowell


David Kastrup wrote:

> Lowell Kirsh <······@cs.ubc.ca> writes:
> 
> 
>>This still doesn't seem to work. With the following defun and call:
>>
>>(defmacro my-add-hooks (hooks &rest body)
>>   `(dolist (hook ',hooks)
>>      (my-add-hook hook ,@body)))
>>
>>(my-add-hooks (inferior-lisp lisp emacs-lisp lisp-interaction)
>>               (imenu-add-to-menubar "Symbols"))
>>
>>I get the following macroexpansion, which looks correct to me, but
>>doesn't actually do anything:
>>
>>(cl-block-wrapper
>>  (catch (quote --cl-block-nil--)
>>    (let ((--dolist-temp--20870 (quote (inferior-lisp lisp emacs-lisp
>>    lisp-interaction)))
>>          hook)
>>      (while --dolist-temp--20870
>>        (setq hook (car --dolist-temp--20870))
>>        (my-add-hook hook
>>                     (imenu-add-to-menubar "Symbols"))
>>        (setq --dolist-temp--20870 (cdr --dolist-temp--20870)))
>>      nil)))
> 
> 
> That's because my-add-hook is a macro, too, and so you just add stuff
> to hook-mode-hook three times.
> 
> 
>>>Apart from that, I consider this sort of thing a crock.  What are
>>>you hoping to achieve that you would not be better off doing by a
>>>proper function instead of a macro?
> 
> 
> In short, I still consider this sort of thing a crock, since you'd be
> better off using a function instead of a macro.  You are unable to
> comprehend what your macros do, and it shows.  Macros are just not
> sensible for this sort of thing.  Use functions instead.  You'll need
> to use some quotes at the outer level, but you'll understand what
> happens.
> 
> To fix the above, you'd need to write something like
> 
> (defmacro my-add-hooks (hooks &rest body)
>    (dolist (hook hooks)
>       `(my-add-hook ,hook ,@body)))
> 
> 
From: Pascal Bourguignon
Subject: Re: elisp macros problem
Date: 
Message-ID: <87oem1bqop.fsf@thalassa.informatimago.com>
Lowell Kirsh <······@cs.ubc.ca> writes:

> Hmmm, I was only trying to use macros because I thought what I was
> trying wasn't possible with functions. Would this be a more
> appropriate approach?
> 
> (defun my-add-hook (hook &rest body)
>    (add-hook (intern (concat (symbol-name hook) "-mode-hook"))
>              `(lambda () ,@body)))
> 
> and then call it like:
> 
> (my-add-hook 'lisp-interaction
>               '(my-translate-paren-types)
>               '(imenu-add-to-menubar "Symbols")
>               )
> 
> This seems a little more verbose with all the quotes, but I guess it
> could be the 'better' approach since it avoids using macros.
> 
> Perhaps my macro approach was a crock. The only reason I defended it
> was becuase I thought you meant that creating the my-add-hook
> functionality itself was the crock.

There is no fundamental difference between a function and a macro.
The only difference, is that functions are called at so called
"run-time" while macros are called at so called "compilation-time".

Now, think about it, when you're using actually a lisp interpreter,
when is "run-time", and when is "compilation-time"?  (You can check
CLHS to see how Common-Lisp  defines these "times").


[There's also the little difference that macro lambda list may involve
destructuring of arguments, while function lambda list don't and
function must do it explicitely with DESTRUCTURE-BIND. But let's
ignore this detail for now.  In lisp that are lexically scoped like
Common-Lisp, there's also that little impact, that scopes can be
modified only at "compilation-time", not anymore at "run-time". So
you'd HAVE to use a macro to process scopes and lexical bindings as
first class objects in lexically scoped lisps.  But since emacs lisp
is not lexically scoped, this difference does not even matter.]


Let's consider a simple macro:

(defmacro myif (condition then &optional else)
   `(cond (,condition ,then)
          (t          ,else)))

(macroexpand-1 '(myif (= a b) 0 (- a b))) --> (COND ((= A B) 0) (T (- A B))) ; T


To see how one can  generate an equivalent function, let's use this
macro:

(defmacro functionify-macro (defmacro-sexp) 
  ;; Naive implementation, for pedagogical purposes only.
  ;; Lacks smart handling of lambda lists...
  (let ((fun (intern (concatenate 'string 
                       (string (second defmacro-sexp)) "-FUN"))))
    `(progn
       (defun ,fun
         ,@(cddr defmacro-sexp))
       (defmacro ,(second defmacro-sexp) ,(third defmacro-sexp)
         (,fun ,@(mapcan (lambda (arg) 
                           (cond 
                            ((listp arg) (list (first arg)))
                            ((char= (character "&") (aref (string arg) 0))
                             nil)
                            ((symbolp arg) (list arg))
                            (t (error "Bad argument"))))
                         (third defmacro-sexp)))))))

(macroexpand-1 '(functionify-macro
                 (defmacro if (condition then &optional else)
                   `(cond (,condition ,then)
                          (t          ,else)))))

--> (PROGN
     (DEFUN IF-FUN (CONDITION THEN &OPTIONAL ELSE)
      `(COND (,CONDITION ,THEN) (T ,ELSE)))
     (DEFMACRO IF (CONDITION THEN &OPTIONAL ELSE) 
         (IF-FUN CONDITION THEN ELSE)))   ; T

So, the macro just calls the function with exactly the same arguments.
Well, "exactly", not exactly, because if that little difference
between "compilation-time" and "run-time", when you invoke a macro,
the arguments are not evalued, but when you call a function they are.
Only that since the macro already has the arguments unevalued, what
they are are literal sexps, not mere values, so when the macro calls
the function, the arguments evaluate (at "compilation-time", remember
the macro executes at "compilation-time", to themselves, and the
function (called by the macro) executed at "compilation-time" will get
literal sexps as arguments.  That's why it'll be able to do the exact
same job as the macro;


(functionify-macro
 (defmacro myif (condition then &optional else)
   `(cond (,condition ,then)
          (t          ,else))))


(macroexpand-1 '(myif (= a b) 0 (- a b))) --> (COND ((= A B) 0) (T (- A B))) ; T
(myif-fun '(= a b) '0 '(- a b))           --> (COND ((= A B) 0) (T (- A B)))


Macros are more difficult to use "programmatically", that is, if you
don't know the exact value of the arguments at "compilation-time",
it's harder to use a macro (you'd have to use eval and have other
difficulties). That's why often you find that a defmacro is just a
thin layer over a function, so you can use the macro at
"compilation-time", and the function at "run-time". [See also the
difference between CLOS (defclass, defmethod MACROS) and MOP
(add-direct-subclass, add-method FUNCTIONS)].


Now, to come back to your problem,

 ;; a function:
 (add-hook-to-mode 'test  
    '(message "test mode hook")
    '(message "first hook"))

or:

  ;; a macro:
  (add-hook-to-mode test 
     (message "test mode hook")
     (message "first hook"))

I don't see the point, compared to: 

    (add-hook 'test-mode-hook
        (lambda () 
            (message "test mode hook")
            (message "first hook")))


Anyway, if you insist on your function, you can always use progn to
minimize the number of quotes:

  (add-hook-to-mode 'test 
     '(progn (message "test mode hook")
             (message "first hook")))



> Well, I'm going with functions now, and I'm also going to get back to
> reading Paul Graham's 'On Lisp', the only comprehensive lisp macros
> book I know of (are there others?)

Beware that when you have a hammer in the hand, 
everything looks like a nail!


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
From: Rob Warnock
Subject: Re: elisp macros problem
Date: 
Message-ID: <Nq6dnZ4xE-sgrprcRVn-sw@speakeasy.net>
Pascal Bourguignon  <····@thalassa.informatimago.com> wrote:
+---------------
| There is no fundamental difference between a function and a macro.
| The only difference, is that functions are called at so called
| "run-time" while macros are called at so called "compilation-time".
| 
| Now, think about it, when you're using actually a lisp interpreter,
| when is "run-time", and when is "compilation-time"?  (You can check
| CLHS to see how Common-Lisp  defines these "times").
+---------------

Minor quibble: A macro-function gets called at "macro expansion time",
which can be either during compilation (see CLHS "3.2.2.2 Minimal
Compilation") or evaluation (CLHS "3.1.2.1.2.2 Macro Forms").

Whether the top-level interactive REPL provides at least "minimal
compilation" or not is an implementation decision. SBCL always does
full compilation (IIUC), whereas CMUCL does only minimal compilation of
interpreted forms, and at that not until the first time the form is
evaluated (by which I'm specifically referring to the body forms of a
function typed to the REPL), for example:

    cmu> (defmacro say-expand (tag)
	   (format t "I'm expanding here: ~s~%" tag)
	   'nil)

    SAY-EXPAND
    cmu> (defun foo ()
	   (say-expand in-foo)
	   37)

    FOO
    cmu> (foo)
    I'm expanding here: IN-FOO
    37
    cmu> (foo)

    37
    cmu> 


-Rob

p.s. Other things besides calling a function can cause its body to
be minimally-compiled in CMUCL, e.g., if right after the definition
of FOO above you called DESCRIBE on it:

    cmu> (describe 'foo)

    FOO is an internal symbol in the COMMON-LISP-USER package.
    Function: #<Interpreted Function FOO {488FD8B1}>
    Function arguments:
      There are no arguments.I'm expanding here: IN-FOO     [ <== LOOK! ]
    Its defined argument types are:
      NIL
    Its result type is:
      *
    Its definition is:
      (LAMBDA () (BLOCK FOO # 37))
    cmu> (foo)

    37
    cmu> 

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Lowell Kirsh
Subject: Re: elisp macros problem
Date: 
Message-ID: <ceh0ft$l17$1@mughi.cs.ubc.ca>
By the way, I never mentioned this, but I broke my wrist pretty badly 
and that's why I'm trying so hard to save keystrokes. It seems like it 
might not have been worth the effort, but it's definitely been a 
learning experience anyway.

Lowell

> Now, to come back to your problem,
> 
>  ;; a function:
>  (add-hook-to-mode 'test  
>     '(message "test mode hook")
>     '(message "first hook"))
> 
> or:
> 
>   ;; a macro:
>   (add-hook-to-mode test 
>      (message "test mode hook")
>      (message "first hook"))
> 
> I don't see the point, compared to: 
> 
>     (add-hook 'test-mode-hook
>         (lambda () 
>             (message "test mode hook")
>             (message "first hook")))
From: Barry Fishman
Subject: Re: elisp macros problem
Date: 
Message-ID: <m3hdrtyr2a.fsf@ecube.site>
David Kastrup <···@gnu.org> writes:

> Lowell Kirsh <······@cs.ubc.ca> writes:
>
>> This still doesn't seem to work. With the following defun and call:
>> 
>> (defmacro my-add-hooks (hooks &rest body)
>>    `(dolist (hook ',hooks)
>>       (my-add-hook hook ,@body)))
>> 
>> (my-add-hooks (inferior-lisp lisp emacs-lisp lisp-interaction)
>>                (imenu-add-to-menubar "Symbols"))
>> 
>> > you hoping to achieve that you would not be better off doing by a
>> > proper function instead of a macro?
>
> In short, I still consider this sort of thing a crock, since you'd be
> better off using a function instead of a macro.  You are unable to
> comprehend what your macros do, and it shows.  Macros are just not
> sensible for this sort of thing.  Use functions instead.  You'll need
> to use some quotes at the outer level, but you'll understand what
> happens.
>
> To fix the above, you'd need to write something like
>
> (defmacro my-add-hooks (hooks &rest body)
>    (dolist (hook hooks)
>       `(my-add-hook ,hook ,@body)))


The body of the defmacro has to return some code.  The dolist
will return just NIL.

Assuming that you want my-add-hooks to create a series of my-add-hook
calls, one would need something like:

(defmacro my-add-hooks (hooks &rest body)
   (cons 'progn (mapcar (lambda (h) `(my-add-hook ,h ,@body)) hooks)))

Its usually easier to do the work in a function and use a macro to
create the syntax you want.  For example, using a function like:

(defun my-add-hooks-fn (hooks func)
  (dolist (hook hooks)
    (add-hook (intern (concat (symbol-name hook) "-mode-hook")) func)))

One can give it the syntax you want with a macro like:

(defmacro my-add-hooks (hooks &rest body)
  `(my-add-hooks-2 ',hooks (lambda () ,@body)))

This has the advantage of creating a single lambda function rather
than multiple lambda functions with the same contents.

This also allows one to build a more complex my-add-hooks-fn without
dealing with the extra complexity of structuring it as a macro.

-- 
Barry Fishman
From: Barry Fishman
Subject: Re: elisp macros problem
Date: 
Message-ID: <m38yd5yqfu.fsf@ecube.site>
Barry Fishman <·············@att.net> writes:

> (defun my-add-hooks-fn (hooks func)
>   (dolist (hook hooks)
>     (add-hook (intern (concat (symbol-name hook) "-mode-hook")) func)))
>
> One can give it the syntax you want with a macro like:
>
> (defmacro my-add-hooks (hooks &rest body)
>   `(my-add-hooks-2 ',hooks (lambda () ,@body)))
>

Opps that should be:

(defmacro my-add-hooks (hooks &rest body)
  `(my-add-hooks-fn ',hooks (lambda () ,@body)))

I got a bit sloppy with my cut and paste.  The use of dolist is kind
of "persona non grata" among emacs maintainers.  I also wrote the
underlying function as:

(defun my-add-hooks-2 (hooks func)
  (mapc (lambda (hook)
          (add-hook (intern (concat (symbol-name hook) "-mode-hook"))
                    func))
        hooks))

-- 
Barry Fishman