🎄 22/25. Reversing a file with Perl 6

Welcome to Day 22 of the Perl 6 One-Liner Advent Calendar! Today, we will continue working with files, and the goal for today is to create a one-liner to print the lines of a text file in reversed order (as tail -r does it).

The first one-liner does the job with the STDIN stream:

.say for $*IN.lines.reverse

Run the program as:

$ perl6 reverse.pl < text.txt

Update. Thanks to the reader comment, we can gain from the fact that $*INcan be omitted in this case, which makes the one-liner even shorter:

.say for lines.reverse

If you want to read the files directly from Perl 6, modify the program a bit to create a file handle out of the command-line argument:

.say for @*ARGS[0].IO.open.lines.reverse

Now you run it as follows:

$ perl6 reverse.pl text.txt

It is important to remember that the default behaviour of the lines method is to exclude the newline characters from the final sequence of lines (the method returns a Seq object, not an array or a list). It may be opposite to what you are used to when working with Perl 5. Using chomp is quite a common practice there.

In Perl 6, the lines method splits the lines based on the value stored in the .nl-in attribute of the IO::Handle object.

You can look at the current value of the line separators with the following tiny script:

dd $_ for @*ARGS[0].IO.open.nl-in

This is what you find there by default:

$["\n", "\r\n"]

The interesting thing is that you can control the behaviour of lines and tell Perl not to exclude the newline characters:

@*ARGS[0].IO.open(chomp => False).lines.reverse.put

The chomp attribute is set to True by default. You can also change the default separator:

@*ARGS[0].IO.open( nl-in => "\r", chomp => False).lines.reverse.put

Notice that without chomping, you do not need an explicit for loop over the lines: in the last two one-liners, the .put method is called directly on the sequence object. In the earlier versions, the strings did not contain the newline characters, and thus they would be printed as a single long line.

I will leave you today with some small homework: Tell the difference between put and say.