Reputation: 9255
I am attempting to write a program whereby I need to process a string character-by-character, including whitespace. This string would be given by the user running the program, from the standard input stream.
I have noticed that the (read)
function stops only after some non-whitespace characters have been captured, and cuts off everything starting with the first whitespace character.
In other words if I do a (read)
function and enter hi to you
, it will return HI
. What I would like my function to return is (#\h #\i #\Space #\t #\o #\Space #\y #\o #\u)
. Can anyone give me some pointers as to how to accomplish this? Sorry guys, I am VERY new to LISP but I like it a lot.
EDIT: One thing I've tried is using (cons) with (read-char). For example: (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) (read-char)))))
. When the user enters "hello", this outputs (#\h #\e #\l #\l . #\o)
, which is close, but what is that extra period doing in there?
Upvotes: 2
Views: 4987
Reputation: 8485
Xach basically answered your main question: you'd probably want to read a line with read-line
and coerce it to a list: (coerce (read-line) 'list)
and then do something with this list.
The reason that read
doesn't work is that it reads and returns s-expressions:
> (car (read))
(foo bar baz) ; this is me typing
FOO
So it just reads the first symbol hi
in the input "hi to you" and stops. Successive calls to read will return the rest:
> (list (read) (read) (read))
hi to you ; me typing again
(HI TO YOU)
You probably still want to use Xach's suggestion to get your input though.
To address your other question, the reason there's a dot in that list of characters is that the expression (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) (read-char)))))
ends with (cons (read-char) (read-char))
which conses two characters together.
Cons creates "cons cells" or Lisp pairs, which are represented as a dotted pair:
> (cons 'a 'b)
(A . B)
Lisp lists are usually formed with nil
or the empty list as the last element. But they are actually represented as linked lists with these cons cells, these are the same:
(a . (b . (c . ())))
(a b c)
They are just usually printed the second way. In your case, the last element is a character, so it's printed as a dotted tail list. Experiment with it at the REPL and it will make sense:
> '(a . (b . c))
(A B . C)
> '(a b . c)
(A B . C)
> '(a b c)
(A B C)
> '(a . (b . (c . nil)))
(A B C)
So what you would want to do with that original expression is this:
> (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) (cons (read-char) nil)))))
(#\h #\e #\l #\l #\o)
Upvotes: 5