unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Need help with macros
@ 2010-01-06 15:40 Cecil Westerhof
  2010-01-06 17:18 ` Cecil Westerhof
  2010-01-06 19:00 ` Pascal J. Bourguignon
  0 siblings, 2 replies; 8+ messages in thread
From: Cecil Westerhof @ 2010-01-06 15:40 UTC (permalink / raw)
  To: help-gnu-emacs

I am trying to make some useful functionality for Gnus. I think that I
should use a macro for that. I made the following macro (the two message
statements are just for debugging):
    (defmacro gnus-group-jump-bind (key-binding group-to-jump-to)
      (message "#%s#%s#" key-binding      (type-of key-binding))
      (message "#%s#%s#" group-to-jump-to (type-of group-to-jump-to))
      (define-key gnus-group-mode-map key-binding
        (lambda ()
          (interactive)
          (gnus-group-jump-to-group group-to-jump-to))))

When calling this with:
    (gnus-group-jump-bind "vjd" "nndraft:drafts")

In the message buffer it gives:
    #vjd#string#
    #nndraft:drafts#string#

And the return value is:
    (lambda nil (interactive) (gnus-group-jump-to-group group-to-jump-to))

This is the first problem. Outside the macro group-to-jump-to is not
existing, I need the value of group-to-jump-to not the name itself. How
do I do this? I tried eval, but that did not work.

But of course I do not want to set the key bindings manually but data
driven. So I wrote the following function:
    (defun gnus-group-do-jump-bind ()
       (dolist (this-jump gnus-group-jump-list)
         (let ((this-group (second this-jump))
               (this-key   (concat "vj" (first this-jump))))
         (gnus-group-jump-bind this-key this-group))))

I defined the used value:
    (setq gnus-group-jump-list
          (list
           '("d" "nndraft:drafts")
           ))

And call the function:
    (gnus-group-do-jump-bind)

This gives in the message buffer:
    #this-key#symbol#
    #this-group#symbol#
    Entering debugger...

And the debug output starts with:
    Debugger entered--Lisp error: (wrong-type-argument arrayp this-key)

I tried to work with symbol-value, but that did not work.

What do I need to do to get this working?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof


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

* Re: Need help with macros
  2010-01-06 15:40 Need help with macros Cecil Westerhof
@ 2010-01-06 17:18 ` Cecil Westerhof
  2010-01-06 19:00 ` Pascal J. Bourguignon
  1 sibling, 0 replies; 8+ messages in thread
From: Cecil Westerhof @ 2010-01-06 17:18 UTC (permalink / raw)
  To: help-gnu-emacs

Cecil Westerhof <Cecil@decebal.nl> writes:

> I am trying to make some useful functionality for Gnus. I think that I
> should use a macro for that. I made the following macro (the two message
> statements are just for debugging):
>     (defmacro gnus-group-jump-bind (key-binding group-to-jump-to)
>       (message "#%s#%s#" key-binding      (type-of key-binding))
>       (message "#%s#%s#" group-to-jump-to (type-of group-to-jump-to))
>       (define-key gnus-group-mode-map key-binding
>         (lambda ()
>           (interactive)
>           (gnus-group-jump-to-group group-to-jump-to))))
>
> When calling this with:
>     (gnus-group-jump-bind "vjd" "nndraft:drafts")
>
> In the message buffer it gives:
>     #vjd#string#
>     #nndraft:drafts#string#
>
> And the return value is:
>     (lambda nil (interactive) (gnus-group-jump-to-group group-to-jump-to))
>
> This is the first problem. Outside the macro group-to-jump-to is not
> existing, I need the value of group-to-jump-to not the name itself. How
> do I do this? I tried eval, but that did not work.
>
> But of course I do not want to set the key bindings manually but data
> driven. So I wrote the following function:
>     (defun gnus-group-do-jump-bind ()
>        (dolist (this-jump gnus-group-jump-list)
>          (let ((this-group (second this-jump))
>                (this-key   (concat "vj" (first this-jump))))
>          (gnus-group-jump-bind this-key this-group))))
>
> I defined the used value:
>     (setq gnus-group-jump-list
>           (list
>            '("d" "nndraft:drafts")
>            ))
>
> And call the function:
>     (gnus-group-do-jump-bind)
>
> This gives in the message buffer:
>     #this-key#symbol#
>     #this-group#symbol#
>     Entering debugger...
>
> And the debug output starts with:
>     Debugger entered--Lisp error: (wrong-type-argument arrayp this-key)
>
> I tried to work with symbol-value, but that did not work.
>
> What do I need to do to get this working?

Found it:
    (setq gnus-group-jump-list
          (list
           '("d" "nndraft:drafts")
           ))

    (defmacro gnus-group-jump-bind (key-binding group-to-jump-to)
      `(define-key gnus-group-mode-map ,(symbol-value key-binding)
        (lambda ()
          (interactive)
          (gnus-group-jump-to-group ,(symbol-value group-to-jump-to)))))

    (defun gnus-group-do-jump-bind ()
       (dolist (this-jump gnus-group-jump-list)
         (let ((this-group (second this-jump))
               (this-key   (concat "vj" (first this-jump))))
         (gnus-group-jump-bind this-key this-group))))

    (gnus-group-do-jump-bind)

And this does what I want. A problem could be that:
     (gnus-group-jump-bind "vjd" "nndraft:drafts")

does not work anymore, but just always use variables solves that
'problem'.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof


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

* Re: Need help with macros
  2010-01-06 15:40 Need help with macros Cecil Westerhof
  2010-01-06 17:18 ` Cecil Westerhof
@ 2010-01-06 19:00 ` Pascal J. Bourguignon
  2010-01-06 19:25   ` Cecil Westerhof
  1 sibling, 1 reply; 8+ messages in thread
From: Pascal J. Bourguignon @ 2010-01-06 19:00 UTC (permalink / raw)
  To: help-gnu-emacs

Cecil Westerhof <Cecil@decebal.nl> writes:

> I am trying to make some useful functionality for Gnus. I think that I
> should use a macro for that. I made the following macro (the two message
> statements are just for debugging):
>     (defmacro gnus-group-jump-bind (key-binding group-to-jump-to)
>       (message "#%s#%s#" key-binding      (type-of key-binding))

I would avoid using the character # in lisp output, since it is
meaningful (readable).

(let ((print-circle t))
  (let* ((a "hello")
         (b (list a a)))
    (print b)))
prints:
(#1="hello" #1#)

(read-from-string "(#1=\"hello\" #1#)")
--> ((#1="hello" #1#) . 16)


In a preceding message, I used "%S" instead.  You should try it!
  

>       (message "#%s#%s#" group-to-jump-to (type-of group-to-jump-to))
>       (define-key gnus-group-mode-map key-binding
>         (lambda ()
>           (interactive)
>           (gnus-group-jump-to-group group-to-jump-to))))

gnus-group-jump-bind has no need to be a macro.  As a macro it is
wrong.  Use defun!


> When calling this with:
>     (gnus-group-jump-bind "vjd" "nndraft:drafts")
>
> In the message buffer it gives:
>     #vjd#string#
>     #nndraft:drafts#string#
>
> And the return value is:
>     (lambda nil (interactive) (gnus-group-jump-to-group group-to-jump-to))
>
> This is the first problem. Outside the macro group-to-jump-to is not
> existing, I need the value of group-to-jump-to not the name itself. How
> do I do this? I tried eval, but that did not work.

By using a function instead of macro.


> But of course I do not want to set the key bindings manually but data
> driven. So I wrote the following function:
>     (defun gnus-group-do-jump-bind ()
>        (dolist (this-jump gnus-group-jump-list)
>          (let ((this-group (second this-jump))
>                (this-key   (concat "vj" (first this-jump))))
>          (gnus-group-jump-bind this-key this-group))))
>
> I defined the used value:
>     (setq gnus-group-jump-list
>           (list
>            '("d" "nndraft:drafts")
>            ))
>
> And call the function:
>     (gnus-group-do-jump-bind)
>
> This gives in the message buffer:
>     #this-key#symbol#
>     #this-group#symbol#
>     Entering debugger...
>
> And the debug output starts with:
>     Debugger entered--Lisp error: (wrong-type-argument arrayp this-key)
>
> I tried to work with symbol-value, but that did not work.
>
> What do I need to do to get this working?

Make it a function.

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


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

* Re: Need help with macros
  2010-01-06 19:00 ` Pascal J. Bourguignon
@ 2010-01-06 19:25   ` Cecil Westerhof
  2010-01-06 19:48     ` Cecil Westerhof
  2010-01-06 20:23     ` Pascal J. Bourguignon
  0 siblings, 2 replies; 8+ messages in thread
From: Cecil Westerhof @ 2010-01-06 19:25 UTC (permalink / raw)
  To: help-gnu-emacs

pjb@informatimago.com (Pascal J. Bourguignon) writes:

>> I am trying to make some useful functionality for Gnus. I think that I
>> should use a macro for that. I made the following macro (the two message
>> statements are just for debugging):
>>     (defmacro gnus-group-jump-bind (key-binding group-to-jump-to)
>>       (message "#%s#%s#" key-binding      (type-of key-binding))
>
> I would avoid using the character # in lisp output, since it is
> meaningful (readable).
>
> (let ((print-circle t))
>   (let* ((a "hello")
>          (b (list a a)))
>     (print b)))
> prints:
> (#1="hello" #1#)
>
> (read-from-string "(#1=\"hello\" #1#)")
> --> ((#1="hello" #1#) . 16)

I do not really understand what happens here -but I am a newbie with
lisp, so that is not that strange-, but I will not use the '#' anymore.


> In a preceding message, I used "%S" instead.  You should try it!

I find the '#' termination more clear, but I can get used to this.
Better safe as sorry.


>>       (message "#%s#%s#" group-to-jump-to (type-of group-to-jump-to))
>>       (define-key gnus-group-mode-map key-binding
>>         (lambda ()
>>           (interactive)
>>           (gnus-group-jump-to-group group-to-jump-to))))
>
> gnus-group-jump-bind has no need to be a macro.  As a macro it is
> wrong.  Use defun!

I could not get the defun working, that is why I thought it had to be
done with a macro. The macro first also did not work. The macro works
now. I'll rewrite the macro to a defun.

I do have a lot of questions. I am glad that you and others are so
helpful. ;-)

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof


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

* Re: Need help with macros
  2010-01-06 19:25   ` Cecil Westerhof
@ 2010-01-06 19:48     ` Cecil Westerhof
  2010-01-06 20:29       ` Pascal J. Bourguignon
  2010-01-06 20:23     ` Pascal J. Bourguignon
  1 sibling, 1 reply; 8+ messages in thread
From: Cecil Westerhof @ 2010-01-06 19:48 UTC (permalink / raw)
  To: help-gnu-emacs

Cecil Westerhof <Cecil@decebal.nl> writes:

>> gnus-group-jump-bind has no need to be a macro.  As a macro it is
>> wrong.  Use defun!
>
> I could not get the defun working, that is why I thought it had to be
> done with a macro. The macro first also did not work. The macro works
> now. I'll rewrite the macro to a defun.

And this is without a macro:
    (defun gnus-group-jump-bind ()
      "Define the key bindings for jumping to groups;"
      (dolist (this-jump gnus-group-jump-list)
        (let ((this-description (second this-jump))
              (this-group       (third  this-jump))
              (this-key         (concat "vj" (first this-jump))))
          (define-key gnus-group-mode-map this-key
            `(lambda ()
              ,this-description
              (interactive)
              (gnus-group-jump-to-group ,this-group))))))

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof


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

* Re: Need help with macros
  2010-01-06 19:25   ` Cecil Westerhof
  2010-01-06 19:48     ` Cecil Westerhof
@ 2010-01-06 20:23     ` Pascal J. Bourguignon
  1 sibling, 0 replies; 8+ messages in thread
From: Pascal J. Bourguignon @ 2010-01-06 20:23 UTC (permalink / raw)
  To: help-gnu-emacs

Cecil Westerhof <Cecil@decebal.nl> writes:

> pjb@informatimago.com (Pascal J. Bourguignon) writes:
>
>>> I am trying to make some useful functionality for Gnus. I think that I
>>> should use a macro for that. I made the following macro (the two message
>>> statements are just for debugging):
>>>     (defmacro gnus-group-jump-bind (key-binding group-to-jump-to)
>>>       (message "#%s#%s#" key-binding      (type-of key-binding))
>>
>> I would avoid using the character # in lisp output, since it is
>> meaningful (readable).
>>
>> (let ((print-circle t))
>>   (let* ((a "hello")
>>          (b (list a a)))
>>     (print b)))
>> prints:
>> (#1="hello" #1#)
>>
>> (read-from-string "(#1=\"hello\" #1#)")
>> --> ((#1="hello" #1#) . 16)
>
> I do not really understand what happens here -but I am a newbie with
> lisp, so that is not that strange-, but I will not use the '#' anymore.

Most output written by print is readable by read.
The strings produced by prin1-to-string are redable by read-from-string.
This is gratis serialization/deserialization provided by lisp.

(prin1-to-string '(42 "abc" def [1 2 3]))
--> "(42 \"abc\" def [1 2 3])"

(car (read-from-string (prin1-to-string '(42 "abc" def [1 2 3]))))
--> (42 "abc" def [1 2 3])


(setf print-circle nil)
(let* ((s "abc")
       (l (list s s)))
   (prin1-to-string l))
--> "(\"abc\" \"abc\")"

(car (read-from-string (let* ((s "abc")
                              (l (list s s)))
                         (prin1-to-string l))))
--> ("abc" "abc")

Here, we get two different strings containing the same characters.

(let ((l2 (car (read-from-string (let* ((s "abc")
                                        (l (list s s)))
                                    (prin1-to-string l))))))
  (eql (first l2) (second l2)))
--> nil

But the original list, l, had twice the same string in it.  By setting
print-circle to t, prin1 and print will use the #= ## notation to make
reference to previously printed objects. (The number is used to
identify the object referenced, when there are several different
objects occuring in various places).

(setf print-circle t)
(let* ((s "abc")
       (l (list s s)))
   (prin1-to-string l))
--> "(#1=\"abc\" #1#)"

When reading these #= and ##, the object is not duplicated anymore.

(car (read-from-string (let* ((s "abc")
                              (l (list s s)))
                         (prin1-to-string l))))
--> (#1="abc" #1#)

(let ((l2 (car (read-from-string (let* ((s "abc")
                                        (l (list s s)))
                                    (prin1-to-string l))))))
  (eql (first l2) (second l2)))
--> t




>> In a preceding message, I used "%S" instead.  You should try it!
>
> I find the '#' termination more clear, but I can get used to this.
> Better safe as sorry.

Well, there's nothing wrong in your usage of #, but it is better in
general to print lisp data that is readable, so that you can easily
read it back if need be.

>>>       (message "#%s#%s#" group-to-jump-to (type-of group-to-jump-to))

(let ((group-to-jump-to "example"))
  (message "%S" (list  group-to-jump-to (type-of group-to-jump-to))))
prints:  ("example" string)

So you can copy-and-paste it and write:

   (set group-to-jump-to (first '("example" string)))

or whatever later.


>>>       (define-key gnus-group-mode-map key-binding
>>>         (lambda ()
>>>           (interactive)
>>>           (gnus-group-jump-to-group group-to-jump-to))))
>>
>> gnus-group-jump-bind has no need to be a macro.  As a macro it is
>> wrong.  Use defun!
>
> I could not get the defun working, that is why I thought it had to be
> done with a macro. The macro first also did not work. The macro works
> now. I'll rewrite the macro to a defun.
>
> I do have a lot of questions. I am glad that you and others are so
> helpful. ;-)

define-key is itself a function so there should be no difficulty in
writing your gnus-group-jump-bind as a function.

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


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

* Re: Need help with macros
  2010-01-06 19:48     ` Cecil Westerhof
@ 2010-01-06 20:29       ` Pascal J. Bourguignon
  2010-01-07 10:35         ` Cecil Westerhof
  0 siblings, 1 reply; 8+ messages in thread
From: Pascal J. Bourguignon @ 2010-01-06 20:29 UTC (permalink / raw)
  To: help-gnu-emacs

Cecil Westerhof <Cecil@decebal.nl> writes:

> Cecil Westerhof <Cecil@decebal.nl> writes:
>
>>> gnus-group-jump-bind has no need to be a macro.  As a macro it is
>>> wrong.  Use defun!
>>
>> I could not get the defun working, that is why I thought it had to be
>> done with a macro. The macro first also did not work. The macro works
>> now. I'll rewrite the macro to a defun.
>
> And this is without a macro:
>     (defun gnus-group-jump-bind ()
>       "Define the key bindings for jumping to groups;"
>       (dolist (this-jump gnus-group-jump-list)
>         (let ((this-description (second this-jump))
>               (this-group       (third  this-jump))
>               (this-key         (concat "vj" (first this-jump))))
>           (define-key gnus-group-mode-map this-key
>             `(lambda ()
>               ,this-description
>               (interactive)
>               (gnus-group-jump-to-group ,this-group))))))

Good.

Two things.  

1- I'd like it better if gnus-group-jump-list was a parameter of the
   function rather than a global variable.


2- You could use destructuring-bind:

    (defun gnus-group-jump-bind (jump-list)
      "Define the key bindings for jumping to groups;"
      (dolist (this-jump jump-list)
        (destructuring-bind (this-key this-description this-group) this-jump
          (let ((binding (concat "vj" this-key)))
            (define-key gnus-group-mode-map binding 
               `(lambda ()
                   ,this-description
                   (interactive)
                   (gnus-group-jump-to-group ,this-group)))))))

    (gnus-group-jump-bind gnus-group-jump-list)


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


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

* Re: Need help with macros
  2010-01-06 20:29       ` Pascal J. Bourguignon
@ 2010-01-07 10:35         ` Cecil Westerhof
  0 siblings, 0 replies; 8+ messages in thread
From: Cecil Westerhof @ 2010-01-07 10:35 UTC (permalink / raw)
  To: help-gnu-emacs

pjb@informatimago.com (Pascal J. Bourguignon) writes:

> 1- I'd like it better if gnus-group-jump-list was a parameter of the
>    function rather than a global variable.

Point taken and implemented. I'll look into my toggle functionality
also. Would be nice to implement it there also without global variables.


> 2- You could use destructuring-bind:
>
>     (defun gnus-group-jump-bind (jump-list)
>       "Define the key bindings for jumping to groups;"
>       (dolist (this-jump jump-list)
>         (destructuring-bind (this-key this-description this-group) this-jump
>           (let ((binding (concat "vj" this-key)))
>             (define-key gnus-group-mode-map binding 
>                `(lambda ()
>                    ,this-description
>                    (interactive)
>                    (gnus-group-jump-to-group ,this-group)))))))

I did not know destructuring-bind. I made it:
    (defun gnus-group-jump-bind (jump-list)
      "Define the key bindings for jumping to groups;"
      (dolist (this-jump jump-list)
        (destructuring-bind (this-key this-description this-group) this-jump
          (define-key gnus-group-mode-map (concat "vj" this-key)
            `(lambda ()
               ,this-description
               (interactive)
               (gnus-group-jump-to-group ,this-group))))))

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof


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

end of thread, other threads:[~2010-01-07 10:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-06 15:40 Need help with macros Cecil Westerhof
2010-01-06 17:18 ` Cecil Westerhof
2010-01-06 19:00 ` Pascal J. Bourguignon
2010-01-06 19:25   ` Cecil Westerhof
2010-01-06 19:48     ` Cecil Westerhof
2010-01-06 20:29       ` Pascal J. Bourguignon
2010-01-07 10:35         ` Cecil Westerhof
2010-01-06 20:23     ` Pascal J. Bourguignon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).