Perl6程序报错“An operation first awaited”,求原因解析
问题分析与解决方案
让我们一步步拆解你遇到的两个错误,并给出修复方案:
1. "Cannot find method 'path'" 错误原因
Perl 6 的 dir() 函数默认返回字符串类型的文件名,而非 IO::Path 对象。当你尝试调用 $file.path 时,字符串没有这个方法,自然会触发报错。
解决这个问题有两种简洁方式:
- 方式一:将字符串转换为
IO::Path对象,调用$file.IO.path替代$file.path - 方式二:让
dir()直接返回IO::Path对象,通过指定参数dir $dir, :as(IO)
2. "An operation first awaited" 错误原因
这个错误通常源于 Promise 状态的异常循环。在你的代码中,当通道关闭后,$dir-channel.receive() 会抛出 X::Channel::ReceiveOnClosed 异常,而你用 .resume 会让循环继续执行——这会导致下一次调用 receive() 再次抛出相同异常,形成无限的异常处理循环,最终触发该错误。
正确的处理逻辑是:捕获到通道关闭的异常时,直接退出循环,而非继续执行。
修正后的完整代码
#!/usr/bin/env perl6 # 一个线程通过dir()读取目录内容写入Channel,N个工作线程从Channel读取并打印文件路径 sub MAIN( Str $dir = ".", Int :$N = 4 ) { my $dir-channel = Channel.new(); my $dir-read = start { # 让dir直接返回IO::Path对象,方便后续调用path方法 $dir-channel.send( $_ ) for dir $dir, :as(IO); $dir-channel.close; } my @workers = (^$N).map: { start { loop { my $file; try { $file = $dir-channel.receive(); CATCH { when X::Channel::ReceiveOnClosed { # 通道已关闭,终止循环 last; } } } # 确保文件对象存在时再打印路径 say $file.path if $file; } } } await $dir-read, @workers; }
额外优化提示
你运行时传入了多个目录参数(traverse-dir0.p6 a b c),但当前 MAIN 函数只接收单个 $dir 参数。如果需要批量处理多个目录,可以修改参数为数组形式:
sub MAIN( *@dirs = ".", Int :$N = 4 )
然后在读取目录的线程中遍历所有传入的目录:
my $dir-read = start { for @dirs -> $d { $dir-channel.send( $_ ) for dir $d, :as(IO); } $dir-channel.close; }
内容的提问来源于stack exchange,提问作者Norman Gaywood
相关产品推荐
相关产品推荐

