From: Yossarian
Subject: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <e0g57j$r75$1@gaudi2.UGent.be>
Hi,

I am trying to write a very simple function that accepts a string as 
input, and that returns a list of strings as output, having a seperate 
list item for every substring without a space.

Example:
input = "something very odd"
output = ("something" "very" "odd")

I tried to do this with the following function, but I can't understand 
why it is not working.

(defun parse(a)
    (setq pos (or (position #\space a) -1) )
    (cond ((= pos -1) (list a))
           ((> pos -1)  (append
                           (parse (subseq a 0 pos))
                           (parse (subseq a (+ pos 1) (length a)))))))

Any comment is welcome!

Regards,

Wouter

From: John Landahl
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <87wteban4w.fsf@mobile.landahl.org>
Yossarian <·········@aixioma.net> writes:
> I am trying to write a very simple function that accepts a string as
> input, and that returns a list of strings as output, having a
> seperate list item for every substring without a space.

It seems we all write one of these eventually.  Here's one I came up
with a while back:

(defun string-split (split-string string)
  "Returns a list containing items in 'string' split from
occurrences of 'split-string'."
  (loop with l = (length split-string)
        for n = 0 then (+ pos l)
        for pos = (search split-string string :start2 n)
        if pos collect (subseq string n pos)
        else collect (subseq string n)
        while pos))

CL-USER> (string-split " " "yeah yeah yeah")
("yeah" "yeah" "yeah")

Also splits on strings of any length:

CL-USER> (string-split "..." "yes...yes...yes")
("yes" "yes" "yes")

But then you're much better off getting CL-PPCRE and using its SPLIT
function, which is far more powerful:

CL-USER> (cl-ppcre:split "\\s" "yeah yeah yeah")
("yeah" "yeah" "yeah")

CL-USER> (cl-ppcre:split "[,:;]" "hello,there:sir")
("hello" "there" "sir")
-- 
John Landahl <····@landahl.org>
http://landahl.org/john
From: Pascal Bourguignon
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <87vetw8dx1.fsf@thalassa.informatimago.com>
Yossarian <·········@aixioma.net> writes:

> Hi,
>
> I am trying to write a very simple function that accepts a string as
> input, and that returns a list of strings as output, having a seperate
> list item for every substring without a space.
>
> Example:
> input = "something very odd"
> output = ("something" "very" "odd")
>
> I tried to do this with the following function, but I can't understand
> why it is not working.
>
> (defun parse(a)
>    (setq pos (or (position #\space a) -1) )
>    (cond ((= pos -1) (list a))
>           ((> pos -1)  (append
>                           (parse (subseq a 0 pos))
>                           (parse (subseq a (+ pos 1) (length a)))))))
>
> Any comment is welcome!

Does this give you a hint?

[2]> (parse  "something very odd")

*** - Lisp stack overflow. RESET
[3]> (trace parse)
;; Tracing function PARSE.
(PARSE)
[4]> (parse  "something very odd")
1. Trace: (PARSE '"something very odd")
2. Trace: (PARSE '"something")
2. Trace: PARSE ==> ("something")
2. Trace: (PARSE '"something very odd")
3. Trace: (PARSE '"something")
3. Trace: PARSE ==> ("something")
3. Trace: (PARSE '"something very odd")
4. Trace: (PARSE '"something")
4. Trace: PARSE ==> ("something")
4. Trace: (PARSE '"something very odd")
5. Trace: (PARSE '"something")
5. Trace: PARSE ==> ("something")
5. Trace: (PARSE '"something very odd")
...

If not yet, try this:

[8]> (defun parse(a)
    (setq pos (or (position #\space a) -1) )
    (cond ((= pos -1) (list a))
           ((> pos -1)  (append
                           (parse (subseq a 0 (print pos)))
                           (parse (subseq a (+ (print pos) 1) (length a)))))))
;;                                             ^^^^^^

WARNING: DEFUN/DEFMACRO: redefining PARSE; it was traced!
PARSE
[9]> (trace parse)
;; Tracing function PARSE.
(PARSE)
[10]> (parse  "something very odd")
1. Trace: (PARSE '"something very odd")
9 
2. Trace: (PARSE '"something")
2. Trace: PARSE ==> ("something")
-1 
2. Trace: (PARSE '"something very odd")
9 
3. Trace: (PARSE '"something")
3. Trace: PARSE ==> ("something")
-1 
3. Trace: (PARSE '"something very odd")
9 
4. Trace: (PARSE '"something")
4. Trace: PARSE ==> ("something")
-1 
4. Trace: (PARSE '"something very odd")
9 
5. Trace: (PARSE '"something")
5. Trace: PARSE ==> ("something")
-1 
5. Trace: (PARSE '"something very odd")
9 
6. Trace: (PARSE '"something")
6. Trace: PARSE ==> ("something")
-1 
6. Trace: (PARSE '"something very odd")
9 
7. Trace: (PARSE '"something")
7. Trace: PARSE ==> ("something")
-1 
7. Trace: (PARSE '"something very odd")
9 


You are modifying a global variable pos, so its value changes between
the two recursive calls to parse.

Use a local variable!  Use LET



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush
From: Yossarian
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <e0ggcv$v4m$1@gaudi2.UGent.be>
Pascal Bourguignon wrote:
> Yossarian <·········@aixioma.net> writes:
> 
> 
>>Hi,
>>
>>I am trying to write a very simple function that accepts a string as
>>input, and that returns a list of strings as output, having a seperate
>>list item for every substring without a space.
>>
>>Example:
>>input = "something very odd"
>>output = ("something" "very" "odd")
>>
>>I tried to do this with the following function, but I can't understand
>>why it is not working.
>>
>>(defun parse(a)
>>   (setq pos (or (position #\space a) -1) )
>>   (cond ((= pos -1) (list a))
>>          ((> pos -1)  (append
>>                          (parse (subseq a 0 pos))
>>                          (parse (subseq a (+ pos 1) (length a)))))))
>>
>>Any comment is welcome!
> 
> 
> Does this give you a hint?
> 
> [2]> (parse  "something very odd")
> 
> *** - Lisp stack overflow. RESET
> [3]> (trace parse)
> ;; Tracing function PARSE.
> (PARSE)
> [4]> (parse  "something very odd")
> 1. Trace: (PARSE '"something very odd")
> 2. Trace: (PARSE '"something")
> 2. Trace: PARSE ==> ("something")
> 2. Trace: (PARSE '"something very odd")
> 3. Trace: (PARSE '"something")
> 3. Trace: PARSE ==> ("something")
> 3. Trace: (PARSE '"something very odd")
> 4. Trace: (PARSE '"something")
> 4. Trace: PARSE ==> ("something")
> 4. Trace: (PARSE '"something very odd")
> 5. Trace: (PARSE '"something")
> 5. Trace: PARSE ==> ("something")
> 5. Trace: (PARSE '"something very odd")
> ...
> 
> If not yet, try this:
> 
> [8]> (defun parse(a)
>     (setq pos (or (position #\space a) -1) )
>     (cond ((= pos -1) (list a))
>            ((> pos -1)  (append
>                            (parse (subseq a 0 (print pos)))
>                            (parse (subseq a (+ (print pos) 1) (length a)))))))
> ;;                                             ^^^^^^
> 
> WARNING: DEFUN/DEFMACRO: redefining PARSE; it was traced!
> PARSE
> [9]> (trace parse)
> ;; Tracing function PARSE.
> (PARSE)
> [10]> (parse  "something very odd")
> 1. Trace: (PARSE '"something very odd")
> 9 
> 2. Trace: (PARSE '"something")
> 2. Trace: PARSE ==> ("something")
> -1 
> 2. Trace: (PARSE '"something very odd")
> 9 
> 3. Trace: (PARSE '"something")
> 3. Trace: PARSE ==> ("something")
> -1 
> 3. Trace: (PARSE '"something very odd")
> 9 
> 4. Trace: (PARSE '"something")
> 4. Trace: PARSE ==> ("something")
> -1 
> 4. Trace: (PARSE '"something very odd")
> 9 
> 5. Trace: (PARSE '"something")
> 5. Trace: PARSE ==> ("something")
> -1 
> 5. Trace: (PARSE '"something very odd")
> 9 
> 6. Trace: (PARSE '"something")
> 6. Trace: PARSE ==> ("something")
> -1 
> 6. Trace: (PARSE '"something very odd")
> 9 
> 7. Trace: (PARSE '"something")
> 7. Trace: PARSE ==> ("something")
> -1 
> 7. Trace: (PARSE '"something very odd")
> 9 
> 
> 
> You are modifying a global variable pos, so its value changes between
> the two recursive calls to parse.
> 
> Use a local variable!  Use LET

Indeed, the idea was to use a local variable ...
Now, if I replace "setq" with "let", then I receive the following error.
Are there extra requirements for using "let"?  What is wrong now?

     (defun parse(a)
         (let pos (or (position #\space a) -1) )
         (cond ((= pos -1) (list a))
               ((> pos -1)  (append
                                 (parse (subseq a 0 pos))
                                 (parse (subseq a (+ pos 1) (length 
a)))))))
;;; Warning: Function not defined: PARSE
;;; An error occurred in function #< COMPILED-FUNCTION: #xD0F828 >:
;;; Error: The variable A is unbound
From: Pascal Bourguignon
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <87mzf87x2r.fsf@thalassa.informatimago.com>
Yossarian <·········@aixioma.net> writes:
>> Use a local variable!  Use LET
>
> Indeed, the idea was to use a local variable ...
> Now, if I replace "setq" with "let", then I receive the following error.
> Are there extra requirements for using "let"?  What is wrong now?
>
>     (defun parse(a)
>         (let pos (or (position #\space a) -1) )
>         (cond ((= pos -1) (list a))
>               ((> pos -1)  (append
>                                 (parse (subseq a 0 pos))
>                                 (parse (subseq a (+ pos 1) (length
> a)))))))
> ;;; Warning: Function not defined: PARSE
> ;;; An error occurred in function #< COMPILED-FUNCTION: #xD0F828 >:
> ;;; Error: The variable A is unbound

It might be a good idea to read some tutorial and some reference
manual.  You wouldn't want to be taken for a Mondoshawan, would you?


Zorg:   I hate warriors, too narrow-minded. I'll tell you what I do
        like: a killer, a died-in-the-wood killer. Cold blooded
        methodical. Now a real killer when he picked up the ZF-1,
        would have immediately asked about the little red button on
        the bottom of the gun.

Aknot: [Scene shifts to Aknot, who is staring in confusion at the
       little red button. He shrugs and pushes it]

Zorg:  [Casually smokes a cigarette as the room with the Mangalores
       blows up] Bring me the priest. 


http://www.imdb.com/title/tt0119116/quotes
http://www.cliki.net/Education
http://www.lispworks.com/documentation/HyperSpec/Front/Contents.htm
http://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm

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

CAUTION: The mass of this product contains the energy equivalent of
85 million tons of TNT per net ounce of weight.
From: Raffael Cavallaro
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <2006033011061227544-raffaelcavallaro@pasdespamsilvousplaitmaccom>
On 2006-03-30 10:48:28 -0500, Pascal Bourguignon 
<······@informatimago.com> said:

> Zorg:   I hate warriors, too narrow-minded. I'll tell you what I do
>         like: a killer, a died-in-the-wood killer.
                                   ^^^^^^
                   should be "dyed-in-the-wool"

The idiom comes from the fact that woolen garments can be dyed before 
spinning, weaving or knitting or they can be dyed afterwards. Those 
dyed beforehand (dyed-in-the-wool) have their color since they were 
wool, even before they became yarn or a piece of cloth. Woolen items 
dyed this way had much longer lasting color.

When speaking of people by analogy, a dyed-in-the-wool x has been an x 
metaphorically since birth and much more strongly so than others who 
came to x later in life.

see: <http://www.answers.com/topic/dyed-in-the-wool> or 
<http://www.factoidcentral.com/phrases/D_files/D_46.html>

BTW, I love Gary Oldman as Zorg ;^)
From: Pascal Bourguignon
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <87odzn7ug0.fsf@thalassa.informatimago.com>
Raffael Cavallaro <················@pas-d'espam-s'il-vous-plait-mac.com> writes:

> On 2006-03-30 10:48:28 -0500, Pascal Bourguignon
> <······@informatimago.com> said:
>
>> Zorg:   I hate warriors, too narrow-minded. I'll tell you what I do
>>         like: a killer, a died-in-the-wood killer.
>                                   ^^^^^^
>                   should be "dyed-in-the-wool"
>
> The idiom comes from the fact that woolen garments can be dyed before
> spinning, weaving or knitting or they can be dyed afterwards. Those
> dyed beforehand (dyed-in-the-wool) have their color since they were
> wool, even before they became yarn or a piece of cloth. Woolen items
> dyed this way had much longer lasting color.
>
> When speaking of people by analogy, a dyed-in-the-wool x has been an x
> metaphorically since birth and much more strongly so than others who
> came to x later in life.
>
> see: <http://www.answers.com/topic/dyed-in-the-wool> or
> <http://www.factoidcentral.com/phrases/D_files/D_46.html>

Ok, I corrected the IMDb quote.


> BTW, I love Gary Oldman as Zorg ;^)


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

THIS IS A 100% MATTER PRODUCT: In the unlikely event that this
merchandise should contact antimatter in any form, a catastrophic
explosion will result.
From: Rob Warnock
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <ifednemd-uP3MbHZRVn-sw@speakeasy.net>
Raffael Cavallaro  <················@pas-d'espam-s'il-vous-plait-mac.com> wrote:
+---------------
| Pascal Bourguignon <······@informatimago.com> said:
| 
| > Zorg:   I hate warriors, too narrow-minded. I'll tell you what I do
| >         like: a killer, a died-in-the-wood killer.
|                                    ^^^^^^
|                    should be "dyed-in-the-wool"
+---------------

Hmmm... Is this a new eggcorn? I don't see it in the database:

    http://eggcorns.lascribe.net/


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <87hd5g7wwv.fsf@thalassa.informatimago.com>
Yossarian <·········@aixioma.net> writes:
>> Use a local variable!  Use LET
>
> Indeed, the idea was to use a local variable ...
> Now, if I replace "setq" with "let", then I receive the following error.
> Are there extra requirements for using "let"?  What is wrong now?
>
>     (defun parse(a)
>         (let pos (or (position #\space a) -1) )
>         (cond ((= pos -1) (list a))
>               ((> pos -1)  (append
>                                 (parse (subseq a 0 pos))
>                                 (parse (subseq a (+ pos 1) (length
> a)))))))
> ;;; Warning: Function not defined: PARSE
> ;;; An error occurred in function #< COMPILED-FUNCTION: #xD0F828 >:
> ;;; Error: The variable A is unbound

It might be a good idea to read some tutorial and some reference
manual.  You wouldn't want to be taken for a Mangalore, would you?


Zorg:   I hate warriors, too narrow-minded. I'll tell you what I do
        like: a killer, a died-in-the-wood killer. Cold blooded
        methodical. Now a real killer when he picked up the ZF-1,
        would have immediately asked about the little red button on
        the bottom of the gun.

Aknot: [Scene shifts to Aknot, who is staring in confusion at the
       little red button. He shrugs and pushes it]

Zorg:  [Casually smokes a cigarette as the room with the Mangalores
       blows up] Bring me the priest. 


http://www.imdb.com/title/tt0119116/quotes
http://www.cliki.net/Education
http://www.lispworks.com/documentation/HyperSpec/Front/Contents.htm
http://www.lispworks.com/documentation/HyperSpec/Body/s_let_l.htm

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

CAUTION: The mass of this product contains the energy equivalent of
85 million tons of TNT per net ounce of weight.
From: Dmitry Gorbatovsky
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <e0hdpb$pm6$1@emma.aioe.org>
Yossarian wrote:

> Hi,
> 
> I am trying to write a very simple function that accepts a string as
> input, and that returns a list of strings as output, having a seperate
> list item for every substring without a space.
> 
> Example:
> input = "something very odd"
> output = ("something" "very" "odd")
> 
> I tried to do this with the following function, but I can't understand
> why it is not working.
> 
> (defun parse(a)
>     (setq pos (or (position #\space a) -1) )
>     (cond ((= pos -1) (list a))
>            ((> pos -1)  (append
>                            (parse (subseq a 0 pos))
>                            (parse (subseq a (+ pos 1) (length a)))))))
> 
> Any comment is welcome!
> 
> Regards,
> 
> Wouter

Or maybe like that:

(defun split-by-one-space (string)

"Returns a list of substrings of string 
divided by ONE space each.
Note: Two consecutive spaces will be seen as if there were an empty string
between them."

    (loop for i = 0 then (1+ j)
          as j = (position #\Space string :start i)
          collect (subseq string i j)
          while j))

From cl-cookbook...

Cheers

-- 
*It is easy to lie with statistics, but it's a lot easier to lie without
them.
From: Alan Crowe
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <86psk26d8m.fsf@cawtech.freeserve.co.uk>
Yossarian <·········@aixioma.net> writes:

> Hi,
> 
> I am trying to write a very simple function that accepts a string as 
> input, and that returns a list of strings as output, having a seperate 
> list item for every substring without a space.
> 
> Example:
> input = "something very odd"
> output = ("something" "very" "odd")
> 
> I tried to do this with the following function, but I can't understand 
> why it is not working.
> 
> (defun parse(a)
>     (setq pos (or (position #\space a) -1) )
>     (cond ((= pos -1) (list a))
>            ((> pos -1)  (append
>                            (parse (subseq a 0 pos))
>                            (parse (subseq a (+ pos 1) (length a)))))))
> 
> Any comment is welcome!

Your design is basically correct but inefficient.

First you need to make pos a local variable

    (let ((pos ..... some number of closing parens
      (cond ....
    ^
    |
    `---- notice the indentation

Your editor will indent your code for you. In emacs its
ctrl-alt-h to set the region to the enclosing defun and
crtl-alt-\ to adjust the indentation.

If this makes it line up

  (let ((pos ... 
  (cond

you have one too many closing parentheses on the previous line

The other way to check is to position the cursor at the end
of the init forms

Position cursor here
                 |
                 |
                 V
(let ((pos ....))
     ^          ^
     |          |
     These two get highlighted as the matching parentheses

In emacs you enable this with meta-x show-paren-mode

Next point is that the position function is carefully
designed to return either the position or Common Lisp's
false value, NIL, with the intention that the value is
directly usable as a boolean. Maybe I should say that the
other way round, Common Lisp's if operator is carefully
designed so that all numbers, including 0, count as
true. Thus the value returned by position is directly usable
as a boolean

(let ((pos ...))
  (if pos
      (code for when position is a number)
      (code for when position is false)))

(append
 (parse (subseq a 0 pos))
 (parse (subseq a (+ pos 1) (length a))))

This could be

(cons
  (subseq a 0 pos)
  (parse (...as before...)))

Position finds the first matching item, so there is no need
to re-parse the leading subsequence.

The end argument to subseq is optional. You could just say

(subseq a (+ pos 1))

and that would also copy all the way to the end.

This brings up the efficiency issue. If there are many
separators the code copies the remaining characters many
times, so the run time is quadratic in the length of the
string when it ought to be linear.

The simplest solution is to add a numerical start argument
to parse, and use the :start key-word for position.

New programming languages often have annoying gaps.
Common Lisp was a unification effort, intended to unify
various previous dialects of Lisp. The upside is that Common
Lisp was an "old" language even when it was "new". The gaps
had all been discovered by programmers working on previous
dialects and Common Lisp ensured that they were all filled.
The ????-side is that it is a big language that combines
lots of useful features. Look at the examples that have been
posted using the LOOP macro.

That presents a problem to the autodidact. If you just
plunge in you are likely to spread yourself too thinly over
many different features and become frustrated. It is
probably best to follow a systematic tutorial. Graham's ANSI
Common Lisp is highly regarded as fast paced tutorial for
those already familiar with programming. (It is the book I
read to learn Common Lisp) It will be interesting to see if
Peter Seibel's impressive Practical Common Lisp

http://www.gigamonkeys.com/book/functions.html

suplants it.

Alan Crowe
Edinburgh
Scotland
From: Yossarian
Subject: Re: Newbie lisp problem: string to list of strings separated by space
Date: 
Message-ID: <e0jelj$1b4$1@gaudi2.UGent.be>
Alan Crowe wrote:
> Yossarian <·········@aixioma.net> writes:
> 
> 
>>Hi,
>>
>>I am trying to write a very simple function that accepts a string as 
>>input, and that returns a list of strings as output, having a seperate 
>>list item for every substring without a space.
>>
>>Example:
>>input = "something very odd"
>>output = ("something" "very" "odd")
>>
>>I tried to do this with the following function, but I can't understand 
>>why it is not working.
>>
>>(defun parse(a)
>>    (setq pos (or (position #\space a) -1) )
>>    (cond ((= pos -1) (list a))
>>           ((> pos -1)  (append
>>                           (parse (subseq a 0 pos))
>>                           (parse (subseq a (+ pos 1) (length a)))))))
>>
>>Any comment is welcome!
> 
> 
> Your design is basically correct but inefficient.
> 
> First you need to make pos a local variable
> 
>     (let ((pos ..... some number of closing parens
>       (cond ....
>     ^
>     |
>     `---- notice the indentation
> 
> Your editor will indent your code for you. In emacs its
> ctrl-alt-h to set the region to the enclosing defun and
> crtl-alt-\ to adjust the indentation.
> 
> If this makes it line up
> 
>   (let ((pos ... 
>   (cond
> 
> you have one too many closing parentheses on the previous line
> 
> The other way to check is to position the cursor at the end
> of the init forms
> 
> Position cursor here
>                  |
>                  |
>                  V
> (let ((pos ....))
>      ^          ^
>      |          |
>      These two get highlighted as the matching parentheses
> 
> In emacs you enable this with meta-x show-paren-mode
> 
> Next point is that the position function is carefully
> designed to return either the position or Common Lisp's
> false value, NIL, with the intention that the value is
> directly usable as a boolean. Maybe I should say that the
> other way round, Common Lisp's if operator is carefully
> designed so that all numbers, including 0, count as
> true. Thus the value returned by position is directly usable
> as a boolean
> 
> (let ((pos ...))
>   (if pos
>       (code for when position is a number)
>       (code for when position is false)))
> 
> (append
>  (parse (subseq a 0 pos))
>  (parse (subseq a (+ pos 1) (length a))))
> 
> This could be
> 
> (cons
>   (subseq a 0 pos)
>   (parse (...as before...)))
> 
> Position finds the first matching item, so there is no need
> to re-parse the leading subsequence.
> 
> The end argument to subseq is optional. You could just say
> 
> (subseq a (+ pos 1))
> 
> and that would also copy all the way to the end.
> 
> This brings up the efficiency issue. If there are many
> separators the code copies the remaining characters many
> times, so the run time is quadratic in the length of the
> string when it ought to be linear.
> 
> The simplest solution is to add a numerical start argument
> to parse, and use the :start key-word for position.
> 
> New programming languages often have annoying gaps.
> Common Lisp was a unification effort, intended to unify
> various previous dialects of Lisp. The upside is that Common
> Lisp was an "old" language even when it was "new". The gaps
> had all been discovered by programmers working on previous
> dialects and Common Lisp ensured that they were all filled.
> The ????-side is that it is a big language that combines
> lots of useful features. Look at the examples that have been
> posted using the LOOP macro.
> 
> That presents a problem to the autodidact. If you just
> plunge in you are likely to spread yourself too thinly over
> many different features and become frustrated. It is
> probably best to follow a systematic tutorial. Graham's ANSI
> Common Lisp is highly regarded as fast paced tutorial for
> those already familiar with programming. (It is the book I
> read to learn Common Lisp) It will be interesting to see if
> Peter Seibel's impressive Practical Common Lisp
> 
> http://www.gigamonkeys.com/book/functions.html
> 
> suplants it.
> 
> Alan Crowe
> Edinburgh
> Scotland

Thanks a lot! That's what I call a valuable answer!  ... think you 
showed some essential properties of functional programming, and Common 
Lisp in particular.  I didn't realize that indentation could be that 
important.

I indeed plan to read Graham's book, which seems to be "the" common lisp 
book.  I used Haskell some years ago, and was to optimistic in the idea 
that it wouldn't take that much time to do some elementary stuff in 
lisp.  I know better now ...

regards,

wouter