This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)
Challenge #2 this week asks for “a script that dumps its own source code”. This is almost a quine, although Mohammad did not name it as such. Specifically, we are given the constraint that perl ch-2.pl | diff - ch-2.pl
must return nothing.
What’s a Quine?
A quine, otherwise known as a self-replicating program, is a program that accepts no input, and produces a copy of its source code as its only output.
This is a stronger definition than what Mohammad has asked for this week: specifically, Mohammad did not add any restrictions on input. So, programs that simply read their own source file would be acceptable this week. Since I felt that was too easy, I have decided to go with the stronger definition of an actual quine, not allowing any input. Still, I’ll include a few solutions to show the various options:
The Cheaty Way
There are a lot of ways to look at quines. One obvious way is to simply read the script’s source and print it:
open my $fh, '<', __FILE__; # Perl
print do { undef $/; <$fh> };
$*PROGRAM.lines».say # Raku
However, the usual definition of a quine forbids any input, and reading the contents of a file certainly qualifies as input. However, the challenge description didn’t specifically ask for a quine by name, so maybe the cheat isn’t a cheat. However, I’m not letting myself off that easily.
The Even More Cheaty Way
Here’s a valid quine and it’s a polyglot:
No, no, please, hold your applause.
The Hard Way
The true challenge (and true beauty) of quines really starts to show through when you disallow all input, and trivial solutions like an empty file (above). Unfortunately, coming up with a novel way to write a quine in Perl after twenty-plus years is rather difficult. So I’ll instead point you towards The Quine Page, curated by Gary P. Thompson II (no relation). I’m going to use one of those.
You’ll see variants of the following construct in almost any discussion around Perl quines, and I’ve never been able to conclusively find out who really came up with the basic idea first. Gary lists V Vinay. That may be true, or V Vinay may have simply been the submitter. In any case, here it is:
$_=q<print"\$_=q<$_>;eval\n">;eval
Don’t trust my (or your) syntax highlighting of any of these examples. Quines exploit a lot of language features in strange ways, and Perl is hard enough to highlight at the best of times.
If someone knows (and, more importantly, can prove) conclusively who the original author of the above is, please let me know!
Update: Dr. V Vinay
December 10th, 2024: Quite out of the blue, I received an email from one Dr. V Vinay, a professor of computer science and, later, founder of an Indian tech firm. Prof. Vinay had this to say, to shed some light on this little bit of Perl history (click to expand):
Message from Dr. V Vinay
I recently came across your page on perl quine, in which you had asked if “someone knows conclusively who the original author of the above is”. I thought I should reach out. I am a professor of Computer Science (from India), and later an Entrepreneur.
It has been more than 25 years since I wrote this code. While the details are hazy in my head, I remember the thrill of crafting the quine quite vividly.
I started with an existing quine that was much much longer (I don’t remember which) and then I spent an entire morning shrinking it character by character to its present form.
Hope this clarifies.
Regards
Vinay
I very much appreciate Prof. Vinay taking the time to send that email. Spending some early 1990s morning golfing a much longer quine into the now more familiar form above, is at once both very relatable, and most certainly a transformative effort worthy of a Perl historical footnote, or __END__
note, if you like.
How does this work? Essentially, it uses string eval to evaluate the contents of $_
, which are set to print"\$_=q<$_>;eval\n"
. This turns the usage of $_
inside the inner q<>
into a recursive use, allowing the script to print its own contents. A good way to learn more is to start from here, and modify it yourself.
Not Satisfied
The above quine will work fine as-is. But the fun part about this particular quine is, the q<>
quoting operator here allows us to add extra string content that will be executed as code, like so:
$_=q<"extra_stuff_here";print"\$_=q<$_>;eval\n">;eval
So I decided to have a little fun with it. If your terminal supports ANSI escape codes (which is pretty much any proper terminal), you can run my solution and see the following:
Raku
Raku supports string eval, too, as well as even more quoting operators and string manipulation, so coming up with a quine is even easier. This one is my own, although it’s so simple it’s entirely possible someone else beat me to it:
{.printf($_)}(<{.printf($_)}(<%s>)>)
Note that there is no trailing newline. I could have added newlines to the output, but I like the conciseness of this solution.
Sorry, no Raku ANSI art. I love Raku, too but, it’s just that one ANSI heart is about my limit in any given week.