Closed coatless closed 3 months ago
From a certain viewpoint, this is expected. It's a consequence of how Emscripten's design line buffers output by default. Buffering line output works better with the behaviour of JavaScript tools such as console.log()
where a partial line cannot be emitted.
Since the line secondly
does not end in a newline character, the output is buffered and not actually emitted until the next \n
is encountered in the output[^1].
I suppose there is a "solution" in that you could set things up so that a newline is always emitted after evaluating code, using R functions like cat("\n")
. However, it is also possible to flush the output buffers directly by using the Module._fsync()
function in the worker thread.
For example, by tweaking webR's prompt handling so that the buffers are flushed whenever a prompt is emitted using something like
webr::eval_js("
const pr = Module.setPrompt;
Module.setPrompt = (prompt) => { Module._fsync(); pr(prompt); }
")
The example then has the behaviour you want:
> webr::eval_js("const pr = Module.setPrompt; Module.setPrompt = (prompt) => { Module._fsync(); pr(prompt); }")
[1] 0
> cat("firstly\nsecondly")
firstly
secondly
>
Admittedly, modifying internal undocumented webR functions is not a good solution if you'd like to opt-in to this non-default behaviour. I will have a think about how best to expose Module._fsync()
to the main thread, and if an option to directly enable this behaviour should be available at webR init time.
EDIT: Possibly the right place for this might be in captureR()/evalR()
rather than flushing during the R prompt. I could be convinced that in that case we really should flush the output by default after the code has been evaluated.
[^1]: You can also see this kind of strange behaviour happening with R in a terminal using your example. At least on my machine the second line of output is secondly>
, where the R prompt has been written directly after the output without a newline.
@georgestagg I appreciate the depth regarding what's going on. One portion of the explanation yielded a great insight:
I suppose there is a "solution" in that you could set things up so that a newline is always emitted after evaluating code, using R functions like cat("\n").
After chatting with another R dev, I was reminded that we could use fill = TRUE
to trigger the cat("\n")
behavior, e.g.
cat("firstly\nsecondly", fill = TRUE)
This is probably a better option (albeit it requires documentation) due to the complexity with exposing Module._fsync()
. So, I think I'm advocating to avoid adding the functionality now that I know what's going on.
So, I think I'm advocating to avoid adding the functionality now that I know what's going on.
Okay, I'll close the issue for now. We can always revisit and document things somewhere if others hit the same issue.
@georgestagg,
I think there now might be something more that has gone wrong with cat():
I can't get cat() to generate any output (see attached)-- tested on iOS (iPad: mobile Safari and Chrome).
Fyi
Hi @SugarRayLua,
The change in https://github.com/r-wasm/webr/issues/412 only applies to use of the webR.captureR()
API. For the webR console shown in your screenshot, the discussion above still applies:
Since the line
secondly
does not end in a newline character, the output is buffered and not actually emitted until the next \n is encountered in the output
e.g.
So, you can either explicitly add a \n
to the end of your string, or use the cat()
argument fill = TRUE
:
Okay, thank you. 😊
Consider:
We would expect the output to be:
Instead, the output is:
However, if we place another cat with
sep = "\n"
after, we get:Demo in REPL:
Code:
/ cc @ute and c.f. https://github.com/coatless/quarto-webr/issues/133