Current-read-interaction returning eof

current-read-interaction is documented as:

(current-read-interaction) → (any/c input-port? -> any)
(current-read-interaction proc) → void?
  proc : (any/c input-port? -> any)

A parameter that determines the current read interaction handler, which is procedure that takes an arbitrary value and an input port and returns an expression read from the input port.

The default read interaction handler accepts src and in and returns

(parameterize ([read-accept-reader #t]
               [read-accept-lang #f])
  (read-syntax src in))

From this I expect it will not return until/unless it has read an expression to return.

At most, I expect it might return a value satisfying eof-object? once --- when the input port has reached eof, for example the user pressed Ctrl-d. Which I handle by exiting the REPL.

And that works as expected for most readers. If there's an expression to return, they return it. If one isn't available, yet, they don't return, yet.

However starting with #lang datalog, and now also with #lang rhombus, I am seeing eof being returned more often, such as for input like "\n", and/or as a kind of "expression delimiter".

This is surprising and confusing. I am not sure what to do about it. Should I ignore eof completely, losing the ability of the user to exit via Ctrl-D?

Probably I'm being dense, but I genuinely don't understand the "use case" for returning eof to mean "no expression available, yet". Why not just... not return, yet? Can someone help me understand the motivation? Could maybe a distinct value could be returned for that case (instead of "overloading" eof), which I could test for and take whatever action is documented for that value?


I agree that the EOF result from #lang rhombus is wrong. The interactive shrubbery reader is meant to use a double newline as a terminator, but it should terminate a non-empty sequence of expressions, and not trigger a mid-stream EOF. I'll fix the shrubbery interactive reader.

More generally, I think you're right that a read interaction handler should not produce EOF unless there was really an EOF (or something that's supposed to mean an EOF instead of an expression) in the input stream.


Thank you!

As for #lang datalog, I'm not sure what to do.

I feel like the "correct" thing is change it not to return until it has an expression (or a "real" EOF from the input port).

But maybe a safer change is have it return a value of struct eof-object:expression derived from eof-object. (Following the example of exn:break and exn:break:terminate and exn:break:hang-up.) That way, Racket Mode could distinguish the two -- without disrupting however this works today with DrRacket (which I don't really understand?) after it checks for eof-object?.

Of course a third choice is "do nothing until/unless some user cares enough to urge doing something", which might be the wisest choice.

In any event if someone wants to update datalog (or even wants me to), I'm glad to update Racket Mode accordingly.


@mflatt I just saw adjust interactive reader to avoid synthesized EOF · racket/rhombus-prototype@3a29344 · GitHub from earlier today.

I did raco pkg update rhombus-prototype, and can confirm this resolves Extra newlines cause Rhombus to send EOF and exit/disconnect REPL · Issue #621 · greghendershott/racket-mode · GitHub.

Thank you!

1 Like