In Perl 5, I can create a filehandle to a string and read or write from the string as if it were a file. This is great for working with tests or templates.
For example:
use v5.10; use strict; use warnings;
my $text = "A\nB\nC\n";
open(my $fh, '<', \$text);
while(my $line = readline($fh)){
print $line;
}
How can I do that in Perl 6? The following doesn't work for Perl 6 (at least not for my instance of Perl6 running on MoarVM 2015.01 from the January 2015 release of Rakudo Star on 64-bit 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
I get the error message:
No such method 'get' for invocant of type 'Str'
in block <unit> at string_fh.p6:8
It's not very surprising that Perl5's open(my $fh, '<', \$text)
is not the same as Perl6's my $fh = $text;
. So the question is: How does one create a virtual file handle from a string in Perl 6 like open(my $fh, '<', \$str)
in Perl 5? Or is that something that has yet to be implemented?
UPDATE (writing to a filehandle in Perl 5)
Likewise, you can write to string filehandles in 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";
Outputs:
My string is 'ABC'
I haven't seen anything remotely similar in Perl 6, yet.
The three basic FileHandles in Perl are STDIN, STDOUT, and STDERR, which represent Standard Input, Standard Output, and Standard Error devices respectively. File Handling is usually done through the open function. Syntax: open(FileHandle, Mode, FileName);
File handling is the most important part in any programming language. A filehandle is an internal Perl structure that associates with a file name. Perl File handling is important as it is helpful in accessing file such as text files, log files or configuration files.
If you want to open a file for reading and writing, you can put a plus sign before the > or < characters. open DATA, "+>file. txt" or die "Couldn't open file file.
The idiomatic way to read line-by-line is the .lines
method, which is available on both Str
and IO::Handle
.
It returns a lazy list which you can pass on to for
, as in
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
(Adapted from #perl6, thanks to Carl Mäsak.)
If you need a more sophisticated mechanism to fake file handles, there's IO::Capture::Simple and IO::String in the ecosystem.
For example:
use IO::Capture::Simple;
my $result;
capture_stdout_on($result);
say "Howdy there!";
say "Hai!";
capture_stdout_off();
say "Captured string:\n" ~$result;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With