jakemiles <jacob.miles@gmail.com> wrote:
+---------------
| Hello. I'm writing a game-playing program in common lisp for a class,
| and I'd like to have a process run while waiting for the user to enter
| input (so the program can do more thinking while the user is thinking).
| I'm familiar with read-char, but I believe this halts everything until
| input is read. Is there any way to just poll an input buffer or
| something every once in a while? I'd prefer not to start playing with
| threads, but if anyone knows of a straightforward option like that I'd
| be interested in learning about it.
+---------------
If you're willing to wait until the user has typed a complete line --
or some other form of "push", such as a ^D under Unix/Linux[1] --
then the CL standard function LISTEN may be what you want. That's
what I use when I'm running a long CPU-bound test and don't want to
use interrupts to stop it. Example:
> (loop for i from 0
until (listen)
do (format t "tick...~%")
(sleep 0.1)
finally (format t "i = ~d~%" i))
tick...
tick...
tick...
tick...
tick...
tick...
<== [typed <CR> here]
i = 6
NIL
>
The <CR> has been read at this point, but it's just leading
whitespace and won't interfere with your next REPL input.
The same thing, but without the (SLEEP 0.1):
> (loop for i from 0
until (listen)
do (format t "tick...~%")
finally (format t "i = ~d~%" i))
tick...
tick...
tick...
...[many, many lines omitted]...
tick...
tick...
tick...
<== [typed <CR> here]
i = 7984
NIL
>
-Rob
[1] Picky details: Most people who haven't dug into it don't understand
that ^D [or whatever character "stty -a" reports for "eof ="]
*isn't* really an "EOF" character at all!! It's a "push" character.
The reason it's normally considered to be the EOF character is that
it's *usually* typed at the beginning of the line, when there is
nothing to read. So the Unix/Linux "read()" call returns 0, which
is the convention for EOF. But if you type one or more characters
other than #\newline and then type your "EOF" character (normally
<Ctrl-D> or ^D), then you will "push" those characters into the
"read()" and it will return however many you had typed. Common
Lisp's READ-LINE lets you tell the difference with its second
return value:
> (read-line)
hello!
"hello!"
NIL
> (read-line)
hel^D <== Note: With CMUCL you may have to type 2 ^D's.
"hel"
T
>
Here's an example of that:
> (loop for i from 0
until (listen)
do (format t "tick...~%")
(sleep 1)
finally (format t "i = ~d~%" i)
(return (multiple-value-list (read-line))))
tick...
tick...
Atick... <== [Typed A here]
tick...
Btick... <== [Typed B here]
tick...
tick...
Ctick... <== [typed C then ^D here]
i = 8
("ABC" T)
>
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607