Я могу создавать дескрипторы файлов для строк в 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 из выпуска Rakudo Star за январь 2015 г. 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

Неудивительно, что open(my $fh, '<', \$text) в Perl5 не то же самое, что my $fh = $text; в Perl6. Возникает вопрос: как создать дескриптор виртуального файла из строки в 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.


person Christopher Bottoms    schedule 24.02.2015    source источник
comment
Кстати. код while (my $line ...) { ... } не имеет лексической области $line, как вы думаете. $line заканчивается лексической областью видимости окружающего контекста, основной части скрипта. Он не ограничен следующими фигурными скобками. Вместо этого объявления лексических переменных с использованием my ограничиваются их закрывающими фигурными скобками. Параметры, напротив, ограничены следующими фигурными скобками, потому что это блок кода, который воздействует на параметры. $line в коде -> $line в первом (единственном) ответе ниже является параметром.   -  person raiph    schedule 25.02.2015
comment
В P5 $line - это необъявленная переменная вне оператора while (use strict; use warnings; покажет это), тогда как в P6 она будет известна.   -  person raiph    schedule 25.02.2015
comment
@raiph Ладно. Теперь я вижу, что ваш первый комментарий полностью относится к Perl 6. Я только что попробовал цикл while (my $line = ... в Perl 6, и вы правы, что $line находится вне цикла. Однако вне цикла он не имеет значения. После цикла $line.say выводит (Any), что означает, что он находится в области видимости, но в основном не определен.   -  person Christopher Bottoms    schedule 25.02.2015
comment
Если $line.say печатает (Any), то это последнее значение, присвоенное $line либо в условном выражении my $line = ... оператора while (обратите внимание, что скобки вокруг условного выражения не нужны), либо в последующем блоке оператора while.   -  person raiph    schedule 04.09.2015


Ответы (1)


Чтение

Идиоматический способ построчного чтения - это .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, спасибо Карлу Месаку.)

Более сложные случаи

Если вам нужен более сложный механизм для подделки дескрипторов файлов, есть IO :: Capture :: Simple и IO :: String в экосистема.

Например:

use IO::Capture::Simple;
my $result;
capture_stdout_on($result);
say "Howdy there!";
say "Hai!";
capture_stdout_off();
say "Captured string:\n" ~$result;
person Christoph    schedule 24.02.2015
comment
Мне нравится педагогическая ценность использования явного -> $foo бита, но на практике выражение for ... часто будет более лаконичным for $text.lines { .foo } там, где для него вызывается метод .foo. (Это переменная $_, которая в любом случае автоматически присваивается, когда пишутся топикализаторы, такие как for.) - person raiph; 25.02.2015
comment
@raiph Это вопрос предпочтений. Раньше я часто использовал $_ в Perl 5, но теперь предпочитаю более явные переменные. Он может быть немного более подробным, но я предпочитаю удобство обслуживания, а не лаконичность. Я рад, что Perl 6 также является TIMTOWTDI. - person Christopher Bottoms; 25.02.2015