Re: Newbie lisp problem: string to list of strings separated by space
- From: Alan Crowe <alan@xxxxxxxxxxxxxxxxxxxxxxx>
- Date: 31 Mar 2006 12:54:33 +0100
Yossarian <yossarian@xxxxxxxxxxx> 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
.
- Follow-Ups:
- References:
- Prev by Date: Re: What language will be used to write the first self aware program?
- Next by Date: Is this a good use for restart-bind?
- Previous by thread: Re: Newbie lisp problem: string to list of strings separated by space
- Next by thread: Re: Newbie lisp problem: string to list of strings separated by space
- Index(es):
Relevant Pages
|
|