能否克隆Perl 6的Proc对象?2018.01版本测试遇报错
报错原因
这个问题出在你使用的**2018.01版本Raku(当时仍称Perl 6)**的API特性上:
- 你代码里的
Proc.new: :out实际创建的是Proc::Async实例,而当时Proc::Async的stdout方法(也就是$f.out背后调用的方法)有严格的签名要求——必须明确指定二进制模式:bin,或者文本模式的编码:enc、换行转换:translate-nl等参数。 - 你的代码直接调用
$f.out.slurp,没有传递任何要求的参数,导致解释器找不到匹配的方法签名,从而抛出"Cannot resolve caller stdout..."的错误。 - 另外,早期版本中
Proc和Proc::Async的边界还没完全理清,API不稳定,这也是导致这类兼容性问题的原因之一。
解决办法
根据你的需求,有几种可行的修复方式:
1. 给out方法补充必填参数
直接按照当时的API要求,给out传递匹配的参数即可。如果要读取文本输出,指定编码:
my $proc = Proc.new: :out; my $f = $proc.clone; $f.spawn: 'ls'; put $f.out(:enc<utf8>).slurp;
如果需要二进制输出,后续自行解码:
my $proc = Proc.new: :out; my $f = $proc.clone; $f.spawn: 'ls'; put $f.out(:bin).slurp.decode('utf8');
2. 改用更明确的Proc::Async写法
既然底层是Proc::Async,直接使用它的标准写法会更稳妥,也更符合当时的最佳实践:
my $proc = Proc::Async.new('ls', :out); my $out-stream = $proc.stdout(:enc<utf8>); $proc.start; await $proc; # 等待进程执行完成 put $out-stream.slurp;
3. 升级到稳定版Raku(推荐)
2018年之后Raku的API已经趋于稳定,后续版本(比如2023.08及以后)中,Proc/Proc::Async的out属性已经简化,你最初写的代码几乎可以直接运行:
my $proc = Proc.new: :out; my $f = $proc.clone; $f.spawn: 'ls'; put $f.out.slurp;
升级后不仅能解决这个问题,还能获得更多新特性和bug修复。
内容的提问来源于stack exchange,提问作者brian d foy
相关产品推荐
相关产品推荐

