在Perl 5中,我可以检查标准输入是否打开并从中读取一行。
onOpen
当我运行它时,输入一行输入,它会读取该行并在继续之前完成其工作。该计划并不关心是否有长时间停顿:
for (;;) {
last if eof(STDIN);
print "Got line " . readline(STDIN);
}
如果我在Perl 6(Rakudo 2017.07)中做同样的事情,程序会马上停止:
$ perl print-stdin.pl
this
Got line this
is
Got line is
a
Got line a
line
Got line line
我真的在一个use v6;
loop {
last if $*IN.eof;
put "Got line " ~ $*IN.get;
}
之后可以给我一行输入(可能来自一个缓慢输出长暂停行的程序)但是我一直支持这个简单的问题。我没有找到一种内置的方法来做这件事(这对于这样一个常见任务来说有点令人惊讶)。
答案 0 :(得分:3)
最近似乎效果更好。
虽然您所写的内容具有竞争条件,因为在调用.eof
之后可以关闭输入。这意味着在.get
被阻止时可能会发生这种情况,因此会返回Nil
。这将导致抛出警告,并打印额外的Got line
。
最好只使用.lines
for $*IN.lines { put "Got line $_" }
或使用.get
的返回值来确定输入何时关闭。
loop {
with $*IN.get {
put "Got line $_"
} else {
last
}
}
如果您想从输入行获取供应:
$*IN.lines.Supply
react {
start whenever $*IN.lines.Supply {
put "Got line $_";
LAST done; # finish the outer 「react」 block when this closes
}
whenever Supply.interval(1) {
put DateTime.now.hh-mm-ss
}
}
22:46:33
22:46:34
a
Got line a
22:46:35
22:46:36
b
Got line b
22:46:37
22:46:38
c
Got line c
22:46:39
22:46:40
d
Got line d
22:46:41
22:46:42
^D # represents Ctrl+D
上面需要start
,因此它不会阻止Supply.interval(1)
供应正常启动。
如果由于某种原因无法实现上述目的,您可以创建这样的供应:
my \in-supply = supply {
# 「await start」 needed so this won't block other things on this thread.
await start loop {
with $*IN.get { # defined (so still open)
emit $_
} else { # not defined (closed)
done; # stop the Supply
# last # stop this loop (never reached)
}
}
}
react {
whenever in-supply {
put "Got line $_";
LAST done # finish the outer 「react」 block when this closes
}
whenever Supply.interval(1) {
put DateTime.now.hh-mm-ss
}
}