*answer_comments is a glob - basically an entry in Perl's symbol table. It is kind of a bundle which contains sub answer_comments, our $answer_comments, our @answer_comments, our %answer_comments and the answer_comments bareword file handle.
If you assign one glob to another, like *xxx = *yyy, then it makes sub xxx and sub yyy aliases for each other, and our $xxx and our $yyy aliases for each other, etc.
use 5.010;
use strict;
use warnings;
our ($xxx, $yyy, @xxx, @yyy);
*xxx = *yyy; # alias
$xxx = 42;
say $yyy; # says "42"
@xxx = (9,9,9);
say "@yyy"; # says "9 9 9"
Anyway, that's what happens when you assign one glob to another glob. But you can also assign references to a glob, in which is doesn't alias the whole bundle, but just the relevant slot within the glob. For example:
use 5.010;
use strict;
use warnings;
our ($xxx, $yyy, @xxx, @yyy);
*xxx = \$yyy; # alias $yyy, but not @yyy
$xxx = 42;
say $yyy; # says "42"
@xxx = (9,9,9);
say "@yyy"; # says nothing
And so one_param returns a coderef, and we can assign it to the glob:
*answers_comments = one_param("answers","comments");
This effectively installs the sub into the package with a given name. Almost as if you'd done:
package ...;
sub answers_comments {
...;
}
(This is what Exporter does internally - that module is not as magic as it seems.)
I say "almost" though. There's one key difference, and that's what the CPAN module Sub::Name takes care of. When the answers_comments method is called, Perl still internally treats it as an anonymous coderef. Which means that stack traces (e.g. Carp) would show it as "__ANON__" rather than "answers_comments".
Naming the sub is also important if you use something like namespace::autoclean which deletes subs it finds in your package that don't look like methods. Naming a sub makes it look like a method.
So Sub::Name is well worth using when you muck around with globs; it's a shame it's not bundled with Perl.
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
|