How can i convert the string "1 2 3 4 5 6 7" into the list (1 2 3 4 5 6 7) elegantly? I am using CLISP.
 
    
    - 136,269
- 10
- 221
- 346
 
    
    - 8,272
- 7
- 41
- 61
- 
                    So, what exactly are you trying to do? "String to list" to me implies going from a string to a list of characters, but your example is reading things separated by whitespace. – mange Sep 18 '11 at 04:49
- 
                    i am a lisp newbie. And i have not find "split" like funtion. Up to now, i can use "parse-integer" to convert "123" to 123. – z_axis Sep 18 '11 at 06:51
- 
                    With cl-ppcre: `(mapcar #'parse-integer (ppcre:split #\space "1 2 3"))` – coredump Mar 05 '17 at 16:01
7 Answers
Here is a recursive solution.
    ;Turns a string into a stream so it can be read into a list
    (defun string-to-list (str)
        (if (not (streamp str))
           (string-to-list (make-string-input-stream str))
           (if (listen str)
               (cons (read str) (string-to-list str))
               nil)))
 
    
    - 383
- 7
- 12
You should use parse-integer in a loop.
For example, using loop:
(let ((string "1 2 3"))
  (loop :for (integer position) := (multiple-value-list 
                                    (parse-integer string
                                                   :start (or position 0)
                                                   :junk-allowed t))
        :while integer
        :collect integer))
⇒ (1 2 3)
If you need better control about the splitting, use the split-sequence or cl-ppcre library.
If you need to parse more general number formats, use the parse-number library.
Libraries are available from Quicklisp.
 
    
    - 50,694
- 11
- 78
- 122
(with-input-from-string (s "1 2 3 4 5 6 7" :index i :start 0 :end 13)
              (list (read s) (read s) (read s) (read s) (read s) (read s)))
(1 2 3 4 5 6 7)
it works however i feel it is not so elegant as there are many read call .
thanks again!
 
    
    - 8,272
- 7
- 41
- 61
- 
                    4`(with-input-from-string (s "1 2 3 4 5 6 7") (loop for x = (read s nil :end) until (eq x :end) collect x))` should work, but note that it will take `"one two three"` to a list of symbols rather than a list of strings. – mange Sep 18 '11 at 07:57
I think this might work:
(setf s "1 2 3 4 5 6 7")
(setf L-temp (coerce s 'list))
This makes a list with spaces as elements. Remove spaces:
(setf L-final (remove #\Space L-temp))
 
    
    - 101
- 8
- 
                    This produces the list `(#\1 #\2 #\3 #\4 #\5 #\6 #\7)`, i. e. a list of digit characters. Aside: don't `setf` variables that do not exist. – Svante Mar 04 '17 at 22:54
- 
                    I see Svante is correct. I tried again and posted the answer using read-from-string. I'm still beginning to learn Lisp. So, I am curious about not "setf variables that do not exist". Is that a violation of functional style? Or does it make my code more confusing in larger programs? – Indinfer Mar 06 '17 at 05:05
- 
                    No, it is just undefined behaviour. You are implicitly creating a global variable that may or may not be _special_ (dynamic). Use `defparameter` or `defvar` to create a new globally special variable, or use `let` (or other constructs introducing a local scope) to create local variables. – Svante Mar 10 '17 at 23:32
- 
                    
I see that Svante is right. My previous attempt did not work. Here is another attempt. I use concatenate to change the string into a list representation. Then I use read-from-string to convert the string (s-2) into an actual list.
(setf s-0 "1 2 3 4 5 6 7")
(setf s-1 (concatenate 'string "(" s ")" ))
(setf s-2 (read-from-string s-1))
I roll it into a function like this:
(defun from-string-to-list (s)
  (let ((L (read-from-string 
           (concatenate 'string "(" s ")"))))
    L))
The only purpose of "let" and "L" is to make the function from-string-to-list return only the list and not return multiple values. read-from-string returns two values: The list and the size of the string, I think.
 
    
    - 101
- 8
That would do,
(with-input-from-string (s "1 2 3 4 5")
   (let ((r nil))
      (do ((line (read s nil 'eof)
                 (read s nil 'eof)))
          ((eql line 'eof))
          (push line r))
   (reverse r)))
 
    
    - 2,960
- 2
- 33
- 60
- 
                    additionally, in the above form, in the first list you can replace a string, here `"1 2 3 4 5"`, with a form like `(read-line stream)`, to read a line from a stream yet not yielding a string but a list. – sçuçu Aug 04 '13 at 12:20
