Это простая программа, она печатает размер терминала при изменении его размера:
#!/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;
Давайте добавим await start { ... }
вокруг цикла:
await start { loop {
given getch() {
### code
}
} }
Теперь эта программа не работает должным образом: она ничего не печатает, когда я изменяю размер терминала, но печатает размер, когда я нажимаю любую клавишу. Обратите внимание, что он по-прежнему корректно обрабатывает нажатие Esc.
Наконец, давайте удалим фигурные скобки, и программа снова заработает как надо:
await start loop {
given getch() {
### code
}
}
Что это за грязное волшебство с start
и брекетами?
Ответ Джонатана замечательный. Может быть, есть способ как-то переименовать вопрос, чтобы он соответствовал ответу?
Я думаю, что хорошим первым шагом было бы принять ответ jnthn. Это оставляет возможность сделать другие вещи: возможно, отредактировать ваш вопрос, хотя я думаю, что все в порядке, оставив все как есть; возможно, другие добавляют сюда ответы (я планирую это сделать); возможно, опубликовав проблему в репозитории NCurses
(хотя я не уверен, что автор ответит); возможно, спросите об этом в IRC; возможно, опубликуя еще один SO.
Оператор loop
(на уровне блока) выполняет итерацию немедленно. Напротив, выражение loop
создает ленивый генератор.
Если в блоке start
есть фигурные скобки, то это явно оператор loop
, потому что он находится в блоке. Таким образом, цикл выполняется в другом потоке.
Без них компилятор считает это выражением loop
(интересный вопрос, должно ли оно быть). start
планирует работу в другом потоке, но работа, которую он планирует, просто создает ленивый генератор, фактически не выполняя никаких итераций. Таким образом, он завершается немедленно, и await
создает ленивый генератор. Поскольку await
находится в контексте стока (пустоты), генератор повторяется. Обратите внимание: поскольку это после await
, цикл выполняется в основном потоке.
Таким образом, вне основного потока фактически выполняется только фигурная форма, и, похоже, она не очень хорошо сочетается с библиотекой NCurses. Боюсь, я понятия не имею, почему так происходит.
Предположительно, вы сделали поведение Raku(do) в центре своего вопроса, потому что казалось, что это «грязная магия с
start
и фигурными скобками», и что это, вероятно, было ключом к разгадке тайны вашего неработающего кода. Но, как объяснил jnthn, поведение Raku(do) соответствует замыслу и не объясняет, почему ваш код не работает. Как сказал jnthn, похоже, что это «выполнение вне основного потока... не очень хорошо сочетается с библиотекойNCurses
». Это означает, что ваш вопрос теперь направляет внимание совершенно в неправильном направлении (если вы хотите выяснить, почему ваш код не работает).