Page 1 of 1

What's wrong with this code?

Posted: Fri Jul 16, 2010 2:36 pm
by joybee
(defun string-split (split-pattern string)
(let ((n 0) (l (length split-pattern)))
(loop
(setf pos (search split-pattern string :start2 n))
(if pos ((collect (subseq string n pos)) (setf n (+ pos l)))
)
(collect (subseq string n)))
)
)

Re: What's wrong with this code?

Posted: Fri Jul 16, 2010 4:25 pm
by calibraxis
First, let's format the code conventionally, so everyone can read it more easily.

Code: Select all

(defun string-split (split-pattern string)
  (let ((n 0)
        (l (length split-pattern)))
    (loop
       (setf pos (search split-pattern string :start2 n))
       (if pos
           ((collect (subseq string n pos))
            (setf n (+ pos l))))
       (collect (subseq string n)))))
Loop isn't as perceptive as you think. It won't understand if you nest collects like that. (Iterate is a bit more understanding.)

Here is a solution which uses more of loop's features. I hope I'm not spoiling it for you.

Code: Select all

(defun string-split (split-pattern string)
  (loop for start = 0 then (+ match (length split-pattern))
        for match = (search split-pattern string :start2 start)
        collect (subseq string start match)
        while match))
If you want to use a more setf-based style, this should help you get started. As you clearly know, the intuition is that you want to collect everything from your starting point to... as far as you can go.

(If you want to be robust, you can check what happens if split-pattern is an empty string, and stop that from happening.)

Re: What's wrong with this code?

Posted: Mon Jul 19, 2010 3:05 pm
by joybee
Thanks, Calibraxis,

I knew the code you gave to me is working. But I can't use "loop for/with " style. When I tried my code, sbcl complained about illegal function call at the setf line and I have no idea why.

Re: What's wrong with this code?

Posted: Mon Jul 19, 2010 9:36 pm
by calibraxis
This section of Practical Common Lisp should help you understand loop better. It is a funky macro, warping some of the intuitive rules of Lisp. When it sees keywords like collect and while, it takes special action.

I think sbcl is looking at

Code: Select all

...
  ((collect (subseq string n pos))
   (setf n (+ pos l)))
...
and not understanding it. (Part of the reason, written in boring legalese, is here in the Hyperspec.)