Hello everyone,
I tried to run this under CMUCL, but it would not use my splitchar
variable. Then I changed the code to not use the variable, but just
split on #\Space, and it worked.
Does anyone have any suggestion on why it does not work.
Is there anyway to make the loop use collect in stead of pushing it on
a list the way i do?
(defun splitloop (string splitchar)
(with-open-stream (output (make-string-output-stream))
(let ((splitwords))
(loop for c across string
do (case c
(splitchar (push (get-output-stream-string output) splitwords)) ; on this line
(t (write-char c output)))
finally (push (get-output-stream-string output) splitwords))
(nreverse splitwords))))
PS:
the reson for making this function is to learn lisp. I have also made
a split-function which use recursion, and i'm going to do some
benchmark on them.
--
Knut Olav B�hmer
_ _
/ / (_)__ __ ____ __
/ /__/ / _ \/ // /\ \/ / ... The choice of a
/____/_/_//_/\.,_/ /_/\.\ GNU generation
An ideal world is left as an exercise to the reader. (Paul Graham)
Here's an implementation using LOOP in all its glory (well, not all):
(defun splitloop (string splitchar)
(with-output-to-string (output)
(loop for c across string
if (char= splitchar c)
collect (get-output-stream-string output) into splitwords
else do (write-char c output)
finally (return-from splitloop
(nconc splitwords
(list (get-output-stream-string output)))))))
I can't think of a better way to do the ``finally'' bit, so it's not
algorithmically more efficient than what you had.
This code removes the issue of having to traverse the list at the end,
but doesn't use LOOP's COLLECT:
(defun splitloop2 (string splitchar)
(let (splitwords last)
(flet ((add-word (word)
(if (null last)
(setf splitwords (list word)
last splitwords)
(setf (rest last) (list word)
last (rest last)))))
(with-output-to-string (output)
(loop for c across string
if (char= splitchar c)
do (add-word (get-output-stream-string output))
else do (write-char c output)
finally (add-word (get-output-stream-string output))))
splitwords)))
The ADD-WORD function could be part of a more general macro for doing this
sort of collection:
(defun splitloop3 (string splitchar)
(with-collection-function (add-word)
(with-output-to-string (output)
(loop for c across string
if (char= splitchar c)
do (add-word (get-output-stream-string output))
else do (write-char c output)
finally (add-word (get-output-stream-string output))))))
You could try implementing WITH-COLLECTION-FUNCTION as a simple exercise.
--
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
"Knut Olav B�hmer" <·····@linpro.no> writes:
> (defun splitloop (string splitchar)
> (with-open-stream (output (make-string-output-stream))
Look up with-output-to-string.
> do (case c
> (splitchar (push (get-output-stream-string output) splitwords))
> (t (write-char c output)))
The keys of a case-form are not evaluated, so here you are comparing
the variable c with the symbol splitchar. Replace it with a cond and
something like char=, and it will work.
--
Frode Vatvedt Fjeld
* Frode Vatvedt Fjeld
> "Knut Olav B�hmer" <·····@linpro.no> writes:
>
> > (defun splitloop (string splitchar)
> > (with-open-stream (output (make-string-output-stream))
>
> Look up with-output-to-string.
I did long time ago. I think it said something about
get-output-stream-string had undefined result on it.
> > do (case c
> > (splitchar (push (get-output-stream-string output) splitwords))
> > (t (write-char c output)))
>
> The keys of a case-form are not evaluated, so here you are comparing
> the variable c with the symbol splitchar. Replace it with a cond and
> something like char=, and it will work.
It's not possible to force an evaluation some how? Anyway it's
probably not the meaning. cond will do. I'll do some benchmark on that
too.
--
Knut Olav B�hmer
_ _
/ / (_)__ __ ____ __
/ /__/ / _ \/ // /\ \/ / ... The choice of a
/____/_/_//_/\.,_/ /_/\.\ GNU generation
An ideal world is left as an exercise to the reader. (Paul Graham)
* "Knut Olav B�hmer" <·····@linpro.no>
| I did long time ago. I think it said something about
| get-output-stream-string had undefined result on it.
Please check up on the documentation again.
| It's not possible to force an evaluation some how?
Well, the macro `case� and its siblings are intended for compile-time
optimization, such that constant dispatch-tables that should cause a
single instruction to select a case may be employed.
--
Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
* 17: Frode Vatvedt Fjeld
> Look up with-output-to-string.
* "Knut Olav B�hmer" <·····@linpro.no>
> | I did long time ago. I think it said something about
> | get-output-stream-string had undefined result on it.
* Erik Naggum
> Please check up on the documentation again.
/me looking:
---------------------------------
Function GET-OUTPUT-STREAM-STRING
Exceptional Situations:
The consequences are undefined if string-output-stream is a stream
that was not produced by make-string-output-stream.
The consequences are undefined if string-output-stream was created
implicitly by with-output-to-string or format.
---------------------------------
/me still not sure.
consequences means the result of running the function?
* Erik Naggum
> | It's not possible to force an evaluation some how?
>
> Well, the macro `case� and its siblings are intended for compile-time
> optimization, such that constant dispatch-tables that should cause a
> single instruction to select a case may be employed.
Ok, i'll try that too, just too see the benchmark. I'll have to wait
until I get home though.
--
Knut Olav B�hmer
_ _
/ / (_)__ __ ____ __
/ /__/ / _ \/ // /\ \/ / ... The choice of a
/____/_/_//_/\.,_/ /_/\.\ GNU generation
An ideal world is left as an exercise to the reader. (Paul Graham)
* Knut Olav B�hmer
> * 17: Frode Vatvedt Fjeld
> > Look up with-output-to-string.
>
>
> * "Knut Olav B�hmer" <·····@linpro.no>
> > | I did long time ago. I think it said something about
> > | get-output-stream-string had undefined result on it.
>
> * Erik Naggum
> > Please check up on the documentation again.
>
> /me looking:
> ---------------------------------
> Function GET-OUTPUT-STREAM-STRING
>
> Exceptional Situations:
>
> The consequences are undefined if string-output-stream is a stream
> that was not produced by make-string-output-stream.
>
> The consequences are undefined if string-output-stream was created
> implicitly by with-output-to-string or format.
> ---------------------------------
> /me still not sure.
>
> consequences means the result of running the function?
Sorry for being annoying, but did I understand the hyperspec
correctly? I thought that since you guys said it should work, that I
had misunderstood something.
When I start with a new programming language, I don't have so much
confidens and trust in what I understand. fex when I read perldoc I
have completely trust in that I understand the documentation. I will
probably get that trust in the hyperspec in a while too. Maybe that is
one of my weaknesses.
--
Knut Olav B�hmer
_ _
/ / (_)__ __ ____ __
/ /__/ / _ \/ // /\ \/ / ... The choice of a
/____/_/_//_/\.,_/ /_/\.\ GNU generation
An ideal world is left as an exercise to the reader. (Paul Graham)
"Knut Olav B�hmer" <·····@linpro.no> writes:
> Sorry for being annoying, but did I understand the hyperspec
> correctly? I thought that since you guys said it should work, that I
> had misunderstood something.
I think you understood it correctly. When I asked you to look up
with-output-to-string, I hadn't noticed you using
get-output-stream-string.
--
Frode Vatvedt Fjeld
Frode Vatvedt Fjeld wrote:
> "Knut Olav B�hmer" <·····@linpro.no> writes:
>
>
>>It's not possible to force an evaluation some how?
>
>
> No.
You can do the following.
(case key
(#.expr1 (...))
(#.expr2 (...)))
#. evaluates the subsequent expression at read time. However, this only
works when the expressions (expr1, expr2) are constants or special
variables, for example.
Pascal
--
Pascal Costanza University of Bonn
···············@web.de Institute of Computer Science III
http://www.pascalcostanza.de R�merstr. 164, D-53117 Bonn (Germany)
Knut Olav B�hmer wrote:
> (defun splitloop (string splitchar)
You may be interested in the function SPLIT-SEQUENCE (or is it PARTITION-
SEQUENCE? I forgot which name they settled on), which was developed
in comp.lang.lisp a while ago. It does the same kind of thing that you're
trying to do, but in a more general way.
Arthur Lemmens