unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* A macro and an unwanted containing list in the resulting form
@ 2007-05-23 11:28 Sebastian Tennant
  2007-05-23 11:39 ` Juanma Barranquero
  0 siblings, 1 reply; 13+ messages in thread
From: Sebastian Tennant @ 2007-05-23 11:28 UTC (permalink / raw)
  To: help-gnu-emacs

Hi all,

Trying to write a little macro to automate building a (cond ...)
expression from an alist, where the alist is of the form:

   (("string" . FORM) ...)

and FORM is evaluated if the string passes an equality test.

Here's where I've got to so far.  As you can see, the cond clauses are
contained within an unwanted list:


  (defmacro build-cond (alist)
    (list 'cond
          (mapcar '(lambda (each)
                     (cons (list 'equal 'my-var (car each)) (list (cdr each))))
                  alist)))

  (macroexpand '(build-cond (("hello" . (message "hi"))
                             ("goodbye" . (message "bye")))
                            ))

  (cond (((equal e "hello") (message "hi"))
        ^((equal e "goodbye") (message "bye"))))
        |                                     ^
        |                                     |
        +--------- unwanted list -------------+

Clearly my approach is wrong (because this is how mapcar behaves), so
what is the best way to go about this?

TIA

Sebastian

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-23 11:28 Sebastian Tennant
@ 2007-05-23 11:39 ` Juanma Barranquero
  2007-05-23 12:51   ` Sebastian Tennant
       [not found]   ` <mailman.1069.1179924576.32220.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 13+ messages in thread
From: Juanma Barranquero @ 2007-05-23 11:39 UTC (permalink / raw)
  To: Sebastian Tennant; +Cc: help-gnu-emacs

On 5/23/07, Sebastian Tennant <sebyte@smolny.plus.com> wrote:


>   (cond (((equal e "hello") (message "hi"))
>         ^((equal e "goodbye") (message "bye"))))
>         |                                     ^
>         |                                     |
>         +--------- unwanted list -------------+
>
> Clearly my approach is wrong (because this is how mapcar behaves), so
> what is the best way to go about this?

Try with

  (defmacro build-cond (alist)
    (append '(cond)
            (mapcar '(lambda (each)
                      (cons (list 'equal 'my-var (car each)) (list (cdr each))))
                    alist)))

Is there any reason to make the argument of build-cond an alist? You could try

(defmacro build-cond (&rest conds)
  (append '(cond)
          (mapcar '(lambda (each)
                    (cons (list 'equal 'my-var (car each)) (list (cdr each))))
                  conds)))

and then use

  (build-cond ("hello" . (message "hi"))
              ("goodbye" . (message "bye"))

             Juanma

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

* Re: A macro and an unwanted containing list in the resulting form
       [not found] <mailman.1062.1179919591.32220.help-gnu-emacs@gnu.org>
@ 2007-05-23 12:04 ` Pascal Bourguignon
  2007-05-23 21:32   ` Sebastian Tennant
       [not found]   ` <mailman.1104.1179956594.32220.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 13+ messages in thread
From: Pascal Bourguignon @ 2007-05-23 12:04 UTC (permalink / raw)
  To: help-gnu-emacs

Sebastian Tennant <sebyte@smolny.plus.com> writes:
> Trying to write a little macro to automate building a (cond ...)
> expression from an alist, where the alist is of the form:
>
>    (("string" . FORM) ...)
>
> and FORM is evaluated if the string passes an equality test.
>
> Here's where I've got to so far.  As you can see, the cond clauses are
> contained within an unwanted list:
>
>
>   (defmacro build-cond (alist)
>     (list 'cond
>           (mapcar '(lambda (each)
>                      (cons (list 'equal 'my-var (car each)) (list (cdr each))))
>                   alist)))
>
>   (macroexpand '(build-cond (("hello" . (message "hi"))
>                              ("goodbye" . (message "bye")))
>                             ))
>
>   (cond (((equal e "hello") (message "hi"))
>         ^((equal e "goodbye") (message "bye"))))
>         |                                     ^
>         |                                     |
>         +--------- unwanted list -------------+
>
> Clearly my approach is wrong (because this is how mapcar behaves), so
> what is the best way to go about this?

It's not bad. Instead of building a new list around the list returned
by mapcar:

         (((equal e "hello") (message "hi"))
          ((equal e "goodbye") (message "bye"))) 

you could just prepend this list with the symbol cond:

   (cons 'cond 
          (mapcar '(lambda (each)
                      (cons (list 'equal 'my-var (car each)) (list (cdr each))))
                   alist))

Now, there are operators that are very useful to build expressions
building expressions:

    backquote   `
    unquote     ,
    unsplice    ,@


Instead of writting:

    (let ((x 'hi) (y 'ho))

       (list 'a 'b 'c x 'd y 'e)   )  ; --> (a b c hi d ho e)

you can write:

    (let ((x 'hi) (y 'ho))

       `(a b c ,x d ,y e)   )         ; --> (a b c hi d ho e)


Now, with a list:

    (let ((x '(1 2 3)))

        `(a b ,x c d)    )            ; --> (a b (1 2 3) c d)

When you want the elements in the list bound to x to appear at the
same level as x, you can use unsplice:

    (let ((x '(1 2 3)))

        `(a b ,@x c d)    )           ; --> (a b 1 2 3 c d)


So when you want to write s-exps, you can easily see what the result
will be:

  (defmacro build-cond (alist)
    `(cond ,@(mapcar (lambda (each)
                        `((equal my-var ,(car each)) ,(cdr each)))
                     alist)))

And never put a quote before a lambda expression!!!  It works by
chance in emacs lisp, but it prevents the compiler to compile the
anonymous function, and it wouldn't work in other lisps.


Also, it would be better if you hadn't magic variable names in your
macro. Instead of using my-var, let the user of the macro decide what
variable name should be tested.  You could also  use a better name
than build-cond; for example, string-case.  And let's improve a little
the syntax, removing one layer of useless parentheses, getting the
list of clauses from the &rest of the arguments:

  (defmacro string-case (var-name &rest alist)
    `(cond ,@(mapcar (lambda (each)
                        `((equal ,var-name ,(car each)) ,(cdr each)))
                     alist)))

So now you can write:

   (string-case e
      ("hello"   . (message "hi"))
      ("goodbye" . (message "bye")))

But if you write:

   (string-case (concat "hel" "lo")
      ("hello"   . (message "hi"))
      ("goodbye" . (message "bye")))

the expansion will evaluate several times (concat "hel" "lo"), which
would be very bad when the expression has side effects.  We need to
take care of that in the macro, building a temporary and unique
variable name with gensym, and binding it to the expression:

  (defmacro string-case (strexpr &rest alist)
    (let ((var-name (gensym)))
       `(let ((,var-name ,strexpr))
          (cond ,@(mapcar (lambda (each)
                         `((equal ,var-name ,(car each)) ,(cdr each)))
                     alist)))))


And finally, it would be better if we could have several forms in each
branches, and if we lost the dot:

  (defmacro string-case (strexpr &rest alist)
    (let ((var-name (gensym)))
       `(let ((,var-name ,strexpr))
          (cond ,@(mapcar (lambda (each)
                         `((equal ,var-name ,(car each)) ,@(cdr each)))
                     alist)))))


(macroexpand '(string-case (aref my-strings (incf i))
                 ("hello"    (message "hi") (message "ho"))
                 ("goodbye"  (message "bye"))))
-->
(let ((G42298 (aref my-strings (incf i))))
  (cond
    ((equal G42298 "hello")
     (message "hi")
     (message "ho"))
    ((equal G42298 "goodbye")
     (message "bye"))))


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

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-23 11:39 ` Juanma Barranquero
@ 2007-05-23 12:51   ` Sebastian Tennant
  2007-05-23 13:14     ` Juanma Barranquero
       [not found]   ` <mailman.1069.1179924576.32220.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 13+ messages in thread
From: Sebastian Tennant @ 2007-05-23 12:51 UTC (permalink / raw)
  To: help-gnu-emacs

Quoth "Juanma Barranquero" <lekktu@gmail.com>:
> On 5/23/07, Sebastian Tennant <sebyte@smolny.plus.com> wrote:
>>   (cond (((equal e "hello") (message "hi"))
>>         ^((equal e "goodbye") (message "bye"))))
>>         |                                     ^
>>         |                                     |
>>         +--------- unwanted list -------------+
>>
>> Clearly my approach is wrong (because this is how mapcar behaves), so
>> what is the best way to go about this?
>
> Try with
>
>  (defmacro build-cond (alist)
>    (append '(cond)
>            (mapcar '(lambda (each)
>                      (cons (list 'equal 'my-var (car each)) (list (cdr each))))
>                    alist)))

Hmm.  Thanks a lot.  It works.  (Now I need to grok exactly why).

> Is there any reason to make the argument of build-cond an alist? You
>could try
>
> (defmacro build-cond (&rest conds)
>  (append '(cond)
>          (mapcar '(lambda (each)
>                    (cons (list 'equal 'my-var (car each)) (list (cdr each))))
>                  conds)))
>
> and then use
>
>  (build-cond ("hello" . (message "hi"))
>              ("goodbye" . (message "bye"))

The reason for the alist is the clauses are being passed as one of a
number of arguments to a function call.

Thanks again.

Sebastian

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-23 12:51   ` Sebastian Tennant
@ 2007-05-23 13:14     ` Juanma Barranquero
  2007-05-23 21:40       ` Sebastian Tennant
  0 siblings, 1 reply; 13+ messages in thread
From: Juanma Barranquero @ 2007-05-23 13:14 UTC (permalink / raw)
  To: Sebastian Tennant; +Cc: help-gnu-emacs

On 5/23/07, Sebastian Tennant <sebyte@smolny.plus.com> wrote:

> Hmm.  Thanks a lot.  It works.  (Now I need to grok exactly why).

Pascal Bourguignong's message contains a good deal of information, and
I'd suggest also carefully studing the Macros node of the Emacs Lisp
Reference.

BTW, Pascal suggests

  (cons 'cond ...)

instead of my

  (append '(cond) ...)

and for the life of me I don't know what was I thinking when I wrote
that. Sleep deprivation, I suppose. By all means follow Pascal's
suggestion.

> The reason for the alist is the clauses are being passed as one of a
> number of arguments to a function call.

Aha, I suspected as much.

             Juanma

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

* Re: A macro and an unwanted containing list in the resulting form
       [not found]   ` <mailman.1069.1179924576.32220.help-gnu-emacs@gnu.org>
@ 2007-05-23 16:57     ` Pascal Bourguignon
  2007-05-23 21:45       ` Sebastian Tennant
                         ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Pascal Bourguignon @ 2007-05-23 16:57 UTC (permalink / raw)
  To: help-gnu-emacs

Sebastian Tennant <sebyte@smolny.plus.com> writes:
>> Is there any reason to make the argument of build-cond an alist? You
>>could try
>>
>> (defmacro build-cond (&rest conds)
>>  (append '(cond)
>>          (mapcar '(lambda (each)
>>                    (cons (list 'equal 'my-var (car each)) (list (cdr each))))
>>                  conds)))
>>
>> and then use
>>
>>  (build-cond ("hello" . (message "hi"))
>>              ("goodbye" . (message "bye"))
>
> The reason for the alist is the clauses are being passed as one of a
> number of arguments to a function call.

If you get the a-list as argument to a function, then you don't need a
macro to process it!   Just write a loop!

(require 'cl)

(defun my-function (string clauses)
  (loop
      for clause in clauses
      until (string= string (car clause))
      finally (eval (cdr clause))))

(my-function "goodbye" '(("hello"   . (message "hi"))
                         ("goodbye" . (message "bye"))))


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

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-23 12:04 ` A macro and an unwanted containing list in the resulting form Pascal Bourguignon
@ 2007-05-23 21:32   ` Sebastian Tennant
       [not found]   ` <mailman.1104.1179956594.32220.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 13+ messages in thread
From: Sebastian Tennant @ 2007-05-23 21:32 UTC (permalink / raw)
  To: help-gnu-emacs

Quoth Pascal Bourguignon <pjb@informatimago.com>:
> So when you want to write s-exps, you can easily see what the result
> will be:
>
>   (defmacro build-cond (alist)
>     `(cond ,@(mapcar (lambda (each)
>                         `((equal my-var ,(car each)) ,(cdr each)))
>                      alist)))

Hmm, that's really good to know.  It's certainly a lot more readable,
but I dread to think how this C-code must look (not that I'm a
C-coder), given that you have unquoted lists within a backquoted list
within an unspliced list within another backquoted list...  It must be
a veritable spaghetti-junction, with a few chopped onions thrown in
for good measure!

> And never put a quote before a lambda expression!!!  It works by
>chance in emacs lisp, but it prevents the compiler to compile the
>anonymous function, and it wouldn't work in other lisps.

Noted, although presumably you mean you shouldn't _directly_ quote a
lambda expression? In the above code, the lambda expression occurs
within an unspliced list, itself within a backquoted list... Ah, I
suppose this has the effect of the lambda expression not being quoted
at all?

> Also, it would be better if you hadn't magic variable names in your
> macro. Instead of using my-var, let the user of the macro decide what
> variable name should be tested.  You could also  use a better name
> than build-cond; for example, string-case.  And let's improve a little
> the syntax, removing one layer of useless parentheses, getting the
> list of clauses from the &rest of the arguments:
>
>   (defmacro string-case (var-name &rest alist)
>     `(cond ,@(mapcar (lambda (each)
>                         `((equal ,var-name ,(car each)) ,(cdr each)))
>                      alist)))
>
> So now you can write:
>
>    (string-case e
>       ("hello"   . (message "hi"))
>       ("goodbye" . (message "bye")))

I understand your point, but I don't think it is necessary in this
case.

I'm writing a wrapper function to make-comint-in-buffer that also sets
up a simple process sentinel given the ("string" . FORM) alist.  The
"string" is matched against the process event ("finished" or "killed",
for example) so the variable is always 'ev' (or whatever variable I
choose to hard-code in the process sentinel's lambda function).

> But if you write:
>
>    (string-case (concat "hel" "lo")
>       ("hello"   . (message "hi"))
>       ("goodbye" . (message "bye")))
>
> the expansion will evaluate several times (concat "hel" "lo"), which
> would be very bad when the expression has side effects.  We need to
> take care of that in the macro, building a temporary and unique
> variable name with gensym, and binding it to the expression:
>
>   (defmacro string-case (strexpr &rest alist)
>     (let ((var-name (gensym)))
>        `(let ((,var-name ,strexpr))
>           (cond ,@(mapcar (lambda (each)
>                          `((equal ,var-name ,(car each)) ,(cdr each)))
>                      alist)))))

Hmm, I think I follow... just!  Excuse me if I annotate what follows
for my benefit (and hopefully other's).

> And finally, it would be better if we could have several forms in each
> branches, and if we lost the dot:

"lost the dot" = "do without cons cells" -----+
                                              |
                                     +--------
                                     |
                                    \/
>   (defmacro string-case (strexpr &rest alist)
>     (let ((var-name (gensym)))
>        `(let ((,var-name ,strexpr))
>           (cond ,@(mapcar (lambda (each)
>                          `((equal ,var-name ,(car each)) ,@(cdr each)))
>                      alist)))))                           ^
                                                            |
I see.  ----------------------------------------------------+--+
                                                               |
> (macroexpand '(string-case (aref my-strings (incf i))        |
>                  ("hello"    (message "hi") (message "ho"))  |
>                  ("goodbye"  (message "bye"))))              |
                                                               |
Unique variable name created by (gensym) ---+                  |
                                            |                  |
           ---------------------------------+                  |
           |                                                   |
          \/                                                   |
> (let ((G42298 (aref my-strings (incf i))))                   |
>   (cond                                                      |
>     ((equal G42298 "hello")                                  |
>      (message "hi") (message "ho")) <--+---------------------+
>     ((equal G42298 "goodbye")          |
>      (message "bye"))))                |
                                         |
"several forms in each branch" ----------+

Well Pascal, thank you for an excellent crash-course in macro
expansion!

I hope my annotations are correct, and not out of place, although
people not reading this in a fixed-with font will no doubt wonder what
on earth is going on, not to mention the other nasty things
line-wrapping news-manglers are inclined to do!

Sebastian

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-23 13:14     ` Juanma Barranquero
@ 2007-05-23 21:40       ` Sebastian Tennant
  0 siblings, 0 replies; 13+ messages in thread
From: Sebastian Tennant @ 2007-05-23 21:40 UTC (permalink / raw)
  To: help-gnu-emacs

Quoth "Juanma Barranquero" <lekktu@gmail.com>:
> and for the life of me I don't know what was I thinking when I wrote
> that. Sleep deprivation, I suppose. By all means follow Pascal's
> suggestion.

Hell, it worked!

>> The reason for the alist is the clauses are being passed as one of a
>> number of arguments to a function call.
>
> Aha, I suspected as much.

But... there's no reason they can't go at the end!

Sebastian

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-23 16:57     ` Pascal Bourguignon
@ 2007-05-23 21:45       ` Sebastian Tennant
       [not found]       ` <mailman.1113.1179959874.32220.help-gnu-emacs@gnu.org>
  2007-05-24 16:12       ` Johan Bockgård
  2 siblings, 0 replies; 13+ messages in thread
From: Sebastian Tennant @ 2007-05-23 21:45 UTC (permalink / raw)
  To: help-gnu-emacs

Quoth Pascal Bourguignon <pjb@informatimago.com>:
> Sebastian Tennant <sebyte@smolny.plus.com> writes:
>>> Is there any reason to make the argument of build-cond an alist? You
>>>could try
>>>
>>> (defmacro build-cond (&rest conds)
>>>  (append '(cond)
>>>          (mapcar '(lambda (each)
>>>                    (cons (list 'equal 'my-var (car each)) (list (cdr each))))
>>>                  conds)))
>>>
>>> and then use
>>>
>>>  (build-cond ("hello" . (message "hi"))
>>>              ("goodbye" . (message "bye"))
>>
>> The reason for the alist is the clauses are being passed as one of a
>> number of arguments to a function call.
>
> If you get the a-list as argument to a function, then you don't need a
> macro to process it!   Just write a loop!
>
> (require 'cl)
>
> (defun my-function (string clauses)
>   (loop
>       for clause in clauses
>       until (string= string (car clause))
>       finally (eval (cdr clause))))
>
> (my-function "goodbye" '(("hello"   . (message "hi"))
>                          ("goodbye" . (message "bye"))))
>

Whoa!  This isn't LISP!  At least it doesn't look like it to me.
Where are the parentheses?  I suppose I haven't got the first idea how
the Common Lisp 'loop' function works...???

Sebastian

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

* Re: A macro and an unwanted containing list in the resulting form
       [not found]   ` <mailman.1104.1179956594.32220.help-gnu-emacs@gnu.org>
@ 2007-05-23 23:48     ` Pascal Bourguignon
  0 siblings, 0 replies; 13+ messages in thread
From: Pascal Bourguignon @ 2007-05-23 23:48 UTC (permalink / raw)
  To: help-gnu-emacs

Sebastian Tennant <sebyte@smolny.plus.com> writes:

>> And finally, it would be better if we could have several forms in each
>> branches, and if we lost the dot:
>
> "lost the dot" = "do without cons cells" -----+
>                                               |
>                                      +--------
>                                      |
>                                     \/
>>   (defmacro string-case (strexpr &rest alist)
>>     (let ((var-name (gensym)))
>>        `(let ((,var-name ,strexpr))
>>           (cond ,@(mapcar (lambda (each)
>>                          `((equal ,var-name ,(car each)) ,@(cdr each)))
>>                      alist)))))                           ^
>                                                             |
> I see.  ----------------------------------------------------+--+
>                                                                |
>> (macroexpand '(string-case (aref my-strings (incf i))        |
>>                  ("hello"    (message "hi") (message "ho"))  |
>>                  ("goodbye"  (message "bye"))))              |
>                                                                |
> Unique variable name created by (gensym) ---+                  |
>                                             |                  |
>            ---------------------------------+                  |
>            |                                                   |
>           \/                                                   |
>> (let ((G42298 (aref my-strings (incf i))))                   |
>>   (cond                                                      |
>>     ((equal G42298 "hello")                                  |
>>      (message "hi") (message "ho")) <--+---------------------+
>>     ((equal G42298 "goodbye")          |
>>      (message "bye"))))                |
>                                          |
> "several forms in each branch" ----------+
>
> Well Pascal, thank you for an excellent crash-course in macro
> expansion!
>
> I hope my annotations are correct, and not out of place, although
> people not reading this in a fixed-with font will no doubt wonder what
> on earth is going on, not to mention the other nasty things
> line-wrapping news-manglers are inclined to do!

They're correct.


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

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

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

* Re: A macro and an unwanted containing list in the resulting form
       [not found]       ` <mailman.1113.1179959874.32220.help-gnu-emacs@gnu.org>
@ 2007-05-24  8:47         ` Tim X
  2007-05-24 13:49           ` Sebastian Tennant
  0 siblings, 1 reply; 13+ messages in thread
From: Tim X @ 2007-05-24  8:47 UTC (permalink / raw)
  To: help-gnu-emacs

Sebastian Tennant <sebyte@smolny.plus.com> writes:

> Quoth Pascal Bourguignon <pjb@informatimago.com>:
>> Sebastian Tennant <sebyte@smolny.plus.com> writes:
>>>> Is there any reason to make the argument of build-cond an alist? You
>>>>could try
>>>>
>>>> (defmacro build-cond (&rest conds)
>>>>  (append '(cond)
>>>>          (mapcar '(lambda (each)
>>>>                    (cons (list 'equal 'my-var (car each)) (list (cdr each))))
>>>>                  conds)))
>>>>
>>>> and then use
>>>>
>>>>  (build-cond ("hello" . (message "hi"))
>>>>              ("goodbye" . (message "bye"))
>>>
>>> The reason for the alist is the clauses are being passed as one of a
>>> number of arguments to a function call.
>>
>> If you get the a-list as argument to a function, then you don't need a
>> macro to process it!   Just write a loop!
>>
>> (require 'cl)
>>
>> (defun my-function (string clauses)
>>   (loop
>>       for clause in clauses
>>       until (string= string (car clause))
>>       finally (eval (cdr clause))))
>>
>> (my-function "goodbye" '(("hello"   . (message "hi"))
>>                          ("goodbye" . (message "bye"))))
>>
>
> Whoa!  This isn't LISP!  At least it doesn't look like it to me.
> Where are the parentheses?  I suppose I haven't got the first idea how
> the Common Lisp 'loop' function works...???
>
> Sebastian
>
You aren't the first to make those comments. CL's loop is one area that
generally creates considerable debate - som argue its not lispy and is
difficult to master. Others argue its a very powerful construct that shows what
you can do with CL. 

I'm still pretty much a novice with CL and will admit that loop and format (the
CL version) are two aspects of CL that took considerably more mental effort to
understand. I now now reasonably confident with using format, though I
constantly have to check the references. Loop on the other hand is still a
concept I get amazed by and one I have a lot more work to do with before I can
honestly say I'm confident with. However, like most of the stuff I've done with
CL, its been one of the most rewarding languages I've learnt for many many
years. I also find the different development style of working in CL extremely
rewarding after years of C, C++, Java, Tcl and Perl. I now find I've gotten to
the point that its productive for me to 'explore' a problem with CL before I
start implementing the solution in another (more readily accepted) language.
This process often exposes subtle issue that are not evident when working on a
solution from an abstract level and I'm finding it saves me time refactoring or
redesigning things to accomadate the increased understanding that occurs as you
work on a problem. 

Tim


-- 
tcross (at) rapttech dot com dot au

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-24  8:47         ` Tim X
@ 2007-05-24 13:49           ` Sebastian Tennant
  0 siblings, 0 replies; 13+ messages in thread
From: Sebastian Tennant @ 2007-05-24 13:49 UTC (permalink / raw)
  To: help-gnu-emacs

Quoth Tim X <timx@nospam.dev.null>:
>>> (require 'cl)
>>>
>>> (defun my-function (string clauses)
>>>   (loop
>>>       for clause in clauses
>>>       until (string= string (car clause))
>>>       finally (eval (cdr clause))))
>>>
>>> (my-function "goodbye" '(("hello"   . (message "hi"))
>>>                          ("goodbye" . (message "bye"))))
>>>
>>
>> Whoa!  This isn't LISP!  At least it doesn't look like it to me.
>> Where are the parentheses?  I suppose I haven't got the first idea how
>> the Common Lisp 'loop' function works...???
>>
>> Sebastian
>>
> You aren't the first to make those comments. CL's loop is one area
> that generally creates considerable debate - som argue its not lispy
> and is difficult to master. Others argue its a very powerful
> construct that shows what you can do with CL.
>
> I'm still pretty much a novice with CL and will admit that loop and
> format (the CL version) are two aspects of CL that took considerably
> more mental effort to understand. I now now reasonably confident
> with using format, though I constantly have to check the
> references. Loop on the other hand is still a concept I get amazed
> by and one I have a lot more work to do with before I can honestly
> say I'm confident with. However, like most of the stuff I've done
> with CL, its been one of the most rewarding languages I've learnt
> for many many years. I also find the different development style of
> working in CL extremely rewarding after years of C, C++, Java, Tcl
> and Perl. I now find I've gotten to the point that its productive
> for me to 'explore' a problem with CL before I start implementing
> the solution in another (more readily accepted) language.  This
> process often exposes subtle issue that are not evident when working
> on a solution from an abstract level and I'm finding it saves me
> time refactoring or redesigning things to accomadate the increased
> understanding that occurs as you work on a problem.

Sounds like CL is definitely something worth exploring (there are _so_
many things worth exploring) but it'll have to wait for another day.
I'm happy with my new-found grasp of macro-expansion for the time
being!

Sebastian

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

* Re: A macro and an unwanted containing list in the resulting form
  2007-05-23 16:57     ` Pascal Bourguignon
  2007-05-23 21:45       ` Sebastian Tennant
       [not found]       ` <mailman.1113.1179959874.32220.help-gnu-emacs@gnu.org>
@ 2007-05-24 16:12       ` Johan Bockgård
  2 siblings, 0 replies; 13+ messages in thread
From: Johan Bockgård @ 2007-05-24 16:12 UTC (permalink / raw)
  To: help-gnu-emacs

Pascal Bourguignon <pjb@informatimago.com> writes:

> If you get the a-list as argument to a function, then you don't need a
> macro to process it!   Just write a loop!

Use `assoc'.

-- 
Johan Bockgård

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

end of thread, other threads:[~2007-05-24 16:12 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.1062.1179919591.32220.help-gnu-emacs@gnu.org>
2007-05-23 12:04 ` A macro and an unwanted containing list in the resulting form Pascal Bourguignon
2007-05-23 21:32   ` Sebastian Tennant
     [not found]   ` <mailman.1104.1179956594.32220.help-gnu-emacs@gnu.org>
2007-05-23 23:48     ` Pascal Bourguignon
2007-05-23 11:28 Sebastian Tennant
2007-05-23 11:39 ` Juanma Barranquero
2007-05-23 12:51   ` Sebastian Tennant
2007-05-23 13:14     ` Juanma Barranquero
2007-05-23 21:40       ` Sebastian Tennant
     [not found]   ` <mailman.1069.1179924576.32220.help-gnu-emacs@gnu.org>
2007-05-23 16:57     ` Pascal Bourguignon
2007-05-23 21:45       ` Sebastian Tennant
     [not found]       ` <mailman.1113.1179959874.32220.help-gnu-emacs@gnu.org>
2007-05-24  8:47         ` Tim X
2007-05-24 13:49           ` Sebastian Tennant
2007-05-24 16:12       ` Johan Bockgård

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).