Input/Output The Definitive Guide
Correctly use Perl 6 IO
This section describes how NOT to do Perl 6 IO.
You may have heard of
$*SPEC and seen some code or books show its usage for splitting and joining path fragments. Some of the routine names it provides may even look familiar to what you've used in other languages.
However, unless you're writing your own IO framework, you don't ever need to use
$*SPEC provides low-level stuff and its use will not only make your code horrible to read, you'll likely introduce security issues (e.g. null characters)!
IO::Path type is the workhorse of Perl 6 world. It caters to all the path manipulation needs as well as provides shortcut routines that let you avoid dealing with file handles. Use that instead of the
Tip: you can join path parts with
/ and feed them to
IO::Path's routines; they'll still do The Right Thing™ with them, regardless of the operating system.
# WRONG!! TOO MUCH WORK!my = open .catpath: '', 'foo/bar', ;my = .slurp;.close;
# RIGHT! Use IO::Path to do all the dirty work my $data = 'foo/bar'.IO.add($file).slurp;
.Str method to stringify
IO::Path objects, unless you just want to display them somewhere for information purposes or something. The
.Str method returns whatever the basic path string the
IO::Path was instantiated with. It doesn't consider the value of
$.CWD attribute. For example, this code is broken:
# WRONG!! .Str DOES NOT USE $.CWD!my = 'foo'.IO;chdir 'bar';run <tar -cvvf archive.tar>, ~;
chdir call changed the value of the current directory, but the
$path we created is relative to the directory before that change.
IO::Path object does know what directory it's relative to. We just need to use
.relative to stringify the object. Both routines return a
Str object; they only differ in whether the result is an absolute or relative path. So, we can fix our code like this:
# RIGHT!! .absolute does consider the value of $.CWD!my = 'foo'.IO;chdir 'bar';run <tar -cvvf archive.tar>, .absolute;# Also good:run <tar -cvvf archive.tar>, .relative;
This code is a mistake:
# WRONG!!my = "foo".IO;
The correct way to perform this operation is use
temp instead of
my. It'll localize the effect of changes to
$*CWD, just like
my would, but it won't make it undefined, so the
.IO coercer will still get the correct old value:
temp = "foo".IO;