Seems like you could solve that by endlessly buffering stdin? Then you'd have to keep passing higher and higher offsets to read from, and old offsets would simply return their original, old values.
It doesn't solve the referential transparency problem. To be referentially transparent, the buffer would need to be fixed in size, and have all of its data input prior to being used the first time. Essentially, it would akin to passing a read-only file as a command line argument to `main`.
While preloading would obviously solve pretty much everything and make all execution trivially deterministic: how is forcing all input-reading to provide an offset not referentially transparent? Particularly when all input is done this way, since e.g. checking the current time is I/O and would need to pass last-result values around to maintain its "state" as well.
The problem is if you pass an offset which the user has not yet input to, you're either going to have to abort or return an error of some kind. If the user inputs to this location later, and you read from it, you've broke referential transparency because you called the same function with the same arguments twice and got a different result.
Why would you have to error, or retain the offset? Block until that input exists, and/or return a higher offset to use for the next call - perhaps add the length of error message so you essentially can't guess and have to show the error has been checked. It doesn't have to match the underlying bytes, it's just a progress marker.
But now every function that reads from stdin needs to pass around an offset of where to read from which is very unergonomical. It also isn't really pure since offset is now state that is changing whenever a function is called.
fn do_stuff(offset: int) -> (string, int) {
x = read_guess(offset)
y = read_name("what's your name: ", offset + len(x))
z = read_guess(offset+len(x)+len(y))
new_offset = offset+len(x)+len(y)+len(z)
return ("name is: {y}, guess is: {x}", new_offset)
}
Ergonomics isn't really the point of a hypothetical extreme system. And no, you can compute offset as a result of all inputs to the system, like I did in my example - just keep passing a "previous state" value around, and compute the next state and return it. Like any other functional system already does 99% of the time.