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
.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.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.
You can look at the current value of the line separators with the following tiny script:
dd $_ for @*ARGS.IO.open.nl-in
This is what you find there by default:
The interesting thing is that you can control the behaviour of lines and tell Perl not to exclude the newline characters:
@*ARGS.IO.open(chomp => False).lines.reverse.put
The chomp attribute is set to True by default. You can also change the default separator:
nl-in => "\r", chomp => False
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.