问题 我可以在Perl 5中为字符串创建文件句柄,如何在Perl 6中完成?


在Perl 5中,我可以为字符串创建一个文件句柄,并从字符串中读取或写入,就好像它是一个文件一样。这非常适合使用测试或模板。

例如:

use v5.10; use strict; use warnings;

my $text = "A\nB\nC\n";

open(my $fh, '<', \$text);

while(my $line = readline($fh)){
    print $line;
}

我怎么能在Perl 6中做到这一点?下列  为Perl 6工作(至少不是我运行的Perl6实例) MoarVM 2015.01 来自 2015年1月Rakudo Star发布 在64位CentOS 6.5上):

# Warning: This code does not work
use v6;

my $text = "A\nB\nC\n";

my $fh = $text;

while (my $line = $fh.get ) {
    $line.say;
}
# Warning: Example of nonfunctional code

我收到错误消息:

No such method 'get' for invocant of type 'Str'
   in block <unit> at string_fh.p6:8

Perl5的表现并不令人惊讶 open(my $fh, '<', \$text) 与Perl6不同 my $fh = $text;。所以问题是:如何从Perl 6中的字符串创建虚拟文件句柄 open(my $fh, '<', \$str) 在Perl 5?还是那个尚未实施的东西?

更新(写入Perl 5中的文件句柄)

同样,您可以在Perl 5中写入字符串文件句柄:

use v5.10; use strict; use warnings;

 my $text = "";
 open(my $fh, '>', \$text);

 print $fh "A";
 print $fh "B";
 print $fh "C";

 print "My string is '$text'\n";

输出:

 My string is 'ABC'

我还没有在Perl 6中看到过类似的东西。


3552
2018-02-24 17:54


起源

顺便说一句。该 while (my $line ...) { ... } 代码没有词汇范围 $line 你认为它的方式。该 $line 最终词汇作用于周围的上下文,脚本的主体。它不限于以下大括号内。而是使用词法变量声明 my 限制在它们的括号内。相反的参数 是 范围限定为以下大括号,因为这些是作用于参数的代码块。该 $line 在里面 -> $line 下面第一个(唯一)答案中的代码是一个参数。 - raiph
在P5中, $line 是一个未申报的变量 while 声明(use strict; use warnings; 将揭示这一点)而在P6中它将是众所周知的。 - raiph
@raiph哦,好的。现在我看到你的第一个评论完全是指Perl 6.我只是试了一个 while (my $line = ... 在Perl 6中循环,你是对的 $line 在循环外面的范围。但是,它没有循环外的值。循环之后, $line.say 版画 (Any),意味着它在范围内,但基本上是未定义的。 - Christopher Bottoms
如果 $line.say 版画 (Any) 那是分配给的最后一个“价值” $line 无论是在 while 声明的条件表达式 my $line = ... (注意条件周围的parens是不必要的)或在随后的 while 声明的块。 - raiph


答案:


逐行阅读的惯用方法是 .lines 方法,两者都有 Str 和 IO::Handle

它返回一个可以传递给的惰性列表 for,如在

my $text = "A\nB\nC\n";

for $text.lines -> $line {
     # do something with $line
}

写作

my $scalar;
my $fh = IO::Handle.new but
         role {
             method print (*@stuff) { $scalar ~= @stuff };
             method print-nl        { $scalar ~= "\n" }
         };

$fh.say("OH HAI");
$fh.say("bai bai");

say $scalar
# OH HAI
# bai bai

(改编自 #perl6,感谢CarlMäsak。)

更高级的案例

如果你需要一个更复杂的机制来伪造文件句柄,那就是 IO ::捕捉::简单 和 IO ::字符串 在里面 生态系统

例如:

use IO::Capture::Simple;
my $result;
capture_stdout_on($result);
say "Howdy there!";
say "Hai!";
capture_stdout_off();
say "Captured string:\n" ~$result;

9
2018-02-24 20:51



我喜欢使用显式的教学价值 -> $foo 有点,但在实践中 for ... 声明通常会更简洁 for $text.lines { .foo } 在哪里 .foo 方法在“它”上调用。 (“它”是变量 $_当一个人写“topicalizers”时,它会自动分配 for。) - raiph
@raiph这是一个偏好问题。我曾经使用过 $_ 在Perl 5中很多,但现在更喜欢更明确的变量。它可能稍微冗长一点,但我要求可维护性而不是简洁。我很高兴Perl 6也是TIMTOWTDI。 - Christopher Bottoms