This is the simple program, it prints a terminal size when you resize it:
#!/bin/env raku
use NCurses;
initscr;
loop {
given getch() {
when 27 { last } # exit when pressing esc
when KEY_RESIZE {
mvprintw 0, 0, "{LINES}x{COLS}";
nc_refresh
}
}
}
endwin;
Let's add await start { ... }
around the loop:
await start { loop {
given getch() {
### code
}
} }
Now this program doesn't work properly: it doesn't print anything when I resize a terminal, but prints the size when I press any key. Note that it still handles esc press correctly.
Finally, let's remove the curly braces and the program will work as it should again:
await start loop {
given getch() {
### code
}
}
What is this dirty magic with start
and braces?
A loop
statement (at block level) iterates immediately. By contrast, a loop
expression produces a lazy generator.
When the start
block has curly braces, then it's clearly a loop
statement, because it's in a block. Thus the loop executes on another thread.
Without them, the compiler is considering it a loop
expression (it's an interesting question whether it should). The start
schedules the work on another thread, but the work it schedules is merely producing a lazy generator, not actually doing any iteration. Thus it completes immediately, and the await
produces the lazy generator. Since the await
is in sink (void) context, the generator is iterated. Note that since this is after the await
, then the loop is executing on the main thread.
So only the curly form actually executes off the main thread, and it would appear that doesn't sit well with the NCurses library. I'm afraid I've no insights into why that would be.