Arc Forumnew | comments | leaders | submitlogin
Readc, readline, and newlines
1 point by zck 4754 days ago | 3 comments
I seem to be missing something on how readc and readline work. They appear to include the prior <Enter> keypress as the first character that is read. So code that is trying to read four characters:

  arc> (let ret "" (repeat 4 (zap + ret (readc))) ret)
Reads only two useful times:

  a
  b
  "\na\nb"
The first two lines are input lines that are concluded with the <Enter> button. 'readline works the same way:

  arc> (readline)
  abc
  "\nabc"
The newline is at the beginning of the string; I would expect the newline that I press after typing (newline) to be consumed by the repl, and the newline that I press after typing "abc" to be in the string. Obviously, I can hack the functionality I want together:

  arc> (def my-readc ((o port (stdin))) (readc port) (readc port))
  #<procedure:zz>
  arc> (my-readc)
  a
  #\a
But it seems like there should be a better way -- is there?


3 points by aw 4754 days ago | link

Pressing <Enter> sends your command line "(readline)\n" to Racket's reader, but Racket's reader only reads enough of the input such as "(readline)" to read a complete expression.

  arc> (readc);
  #\;

  arc> (readline);hello there
  ";hello there"
A reasonable fix would be for the REPL loop, when it knows its input is coming from the terminal and so won't see the final line of input unless you've pressed enter, to do its own "(readline)" before evaluating the expression, and so to consume the excess input.

-----

1 point by zck 4754 days ago | link

Interesting, and not entirely wanted, I think. Is there a way to prompt for a new character? I don't see a way to clear out a port; peekc waits for a character to peek at; readall waits until you type nil.

-----

2 points by rocketnia 4754 days ago | link

Scheme's 'char-ready? is probably close to what you're looking for. It returns #f if the runtime can guarantee that the stream would have blocked if it were read from at that time, and otherwise it returns #t.

  ; This exploits an Arc 3.1 bug to drop to Racket (as seen at
  ; http://arclanguage.org/item?id=11838). It's unnecessary on Anarki.
  (mac $ (racket-expr)
    `(cdr `(nil . ,,racket-expr)))
  
  (def discard-input ((o str (stdin)))
    " Reads all the characters from the stream, giving up partway if it
      can determine the stream would block. The return value is `nil'. "
    (while:and $.char-ready?.str readc.str))
  
  
  arc>
    (do (pr "enter something> ")
        (discard-input)
        (prn "The first character was " (tostring:write:readc) ".")
        (discard-input))
  enter something> something
  The first character was #\s.
  nil
  arc>

-----