我在 Raku 中有很好的代码:
#!/usr/bin/env perl6
CONTROL {
when CX::Warn {
note $_;
die
}
}
use fatal;
role KeyRequired {
method AT-KEY (key) {
die "Key {key} not found" unless self.EXISTS-KEY(key);
nextsame
}
}
sub execute ($cmd) {
put $cmd;
my $proc = shell $cmd, :err, :out;
if $proc.exitcode != 0 {
put 'exit code = ' ~ $proc.exitcode;
put 'stderr ' ~ $proc.err.slurp;
put 'stdout ' ~ $proc.out.slurp;
die
}
}
execute "ls *.p6"
我说"优秀"是因为 Raku 版本运行命令,返回退出代码,并在需要时打印 stdout/stderr,并且所有这些都以易于阅读和易于理解的方式进行。
通读 Perl5 手册IPC::Run
https://metacpan.org/pod/IPC::Run 我遇到了似乎是最好的 Perl5 方法,但我发现那里使用的方法比 Raku 做事方式更不容易阅读和理解。
通读手册以了解我能找到IPC::Run
最好的是:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie qw(:all);
use IPC::Run qw(run timeout);
sub execute {
my $cmd = shift;
my @cat = ('cat', __FILE__); # Raku doesn't need to split the string into an array
run @cat, undef, my $out, my $err, timeout( 10 ) or die "cat: $?";
if ($out ne '') {
say "$out = $out";
}
if ($err ne '') {
say "$err = $err";
}
}
execute("cat " . __FILE__);
execute("cat __Fle"); #intentionally wrong to produce an error
如何重写 Perl5,使其像 Raku 代码一样易于阅读和使用?
你不公平地加载了 Perl 5 示例,有很多额外的绒毛,而且你没有在 Raku 代码中处理很多事情。例如,不管变量中有什么,你都会在 Raku 中输出结果,但在 Perl 5 中测试变量。
你的 Perl 5 看起来更像这样:
use v5.30;
use IPC::Run qw(run timeout);
sub execute {
my @command = @_;
run @command, undef, my $out, my $err, timeout( 10 )
or die "cat: $?";
say "$out = $out";
say "$err = $err";
}
execute("cat ", __FILE__);
池上在他的 pastebin 链接中提供了这个版本:
sub execute {
my ($command) = @_;
if (! run $command, undef, my $out, my $err, timeout( 10 ) ) {
say "exit code = $?";
say "stderr $err";
put "stdout $out";
die "Died";
}
}
在这两种情况下,都有一件有趣的事情需要注意。如果退出代码不为零,则假设错误(Raku 假设这一点,这就是为什么您必须担心不会使结果下沉的原因(。但是,许多有用的程序不遵循该约定。例如,git merge base
使用退出值 1 表示"不是祖先",使用所有大于 1 的退出值表示错误。命令行grep
类似。Sendmail 的退出代码为 75,表示某些事情没有解决,但它稍后会重试。
Raku对此有意见,忽略了这种事情,并且不允许你告诉Proc它应该接受哪些退出值作为成功退出。Perl 5 不是那么固执己见。使用or die
或! ...
实际上是在说"退出代码不为零",但这实际上不是一个足够好的描述。在很多情况下,你可以侥幸逃脱,但至少 Perl 5 不会为你做决定。如果您展开 Raku 示例以检查文本值并确定是否成功,它看起来会很混乱。
但是,请注意,Raku的shell
文档指出它是不安全的,您应该改用run
。
就其价值而言,我不认为 Raku 的进程间通信值得信赖。在许多情况下,我认为它的IPC设计被忽视了。例如,请参阅 Perl 6 的 $*OUT 是否会更改子进程的标准输出?我在错误报告和Stackoverflow中还有其他几个IPC问题,几乎没有一个得到满意的答案。大多数情况下,我认为这是因为没有人考虑那么多。当然,Raku是由一个小团队开发的,这是一个大项目,但是当涉及到生产编程时,这不是一个因素。
更多乐壳怪异:
- Perl 6 的 shell(( 使用哪个 shell?