Perl::...iteral(3pm)

πŸ’… NAME πŸ’…

Perl::Critic::Policy::ValuesAndExpressions::UnexpandedSpecialLiteral β€” bestie, this is the policy for when you use specials like __PACKAGE__ literally and the vibes are, frankly, not it.


✨ DESCRIPTION ✨

Okay so this policy lives inside the Perl::Critic::Pulp add-on. It catches those little oopsie moments where the special literals __FILE__, __LINE__ and __PACKAGE__ (peep "Special Literals" in perldata for the lore) get used with => or as a hash subscript β€” and so they never expand into the actual filename, line number, or package name. Tragic. πŸ’€

my $seen = { __FILE__ => 1 };          # bad
return ('At:'.__LINE__ => 123);        # bad
$obj->{__PACKAGE__}->{myextra} = 123;  # bad

In every single one of those cases, all you actually get is the plain string "__FILE__", "__LINE__" or "__PACKAGE__", exactly as if you'd written:

my $seen = { '__FILE__' => 1 };
return ('At:__LINE__' => 123);
$obj->{'__PACKAGE__'}->{'myextra'} = 123;

…where, let's be real, you almost certainly meant it to expand to the filename and friends. 🫠 Because of that, this policy is filed under the "bugs" theme (see "POLICY THEMES" in Perl::Critic).

And no, expression forms like this:

'MyExtra::'.__PACKAGE__ => 123    # bad

are still bad, bestie. Because the word sitting immediately to the left of a => gets quoted even when that word is only part of an expression. The audacity, honestly.

So if you genuinely want a string "__FILE__" or whatever? The suggestion is simple: just write the quotes. Even if quoting in hash constructors is not your usual vibe. It passes this policy, and it makes it crystal clear to literally everyone that yes, you wanted the literal string. Periodt. πŸ’…

Now β€” the __PACKAGE__ literal is new in Perl 5.004, but this policy gets applied to all code regardless. And even if you're targeting an earlier Perl, adding the extra quotes will make it obvious to users of later Perl that a literal string "__PACKAGE__" is genuinely what you intended. Communication, slay. 🌸

πŸŽ€ Fat Comma After Newline πŸŽ€

A => fat comma only quotes when it's on the same line as the bareword before it, so in this next one __PACKAGE__ is not quoted, and therefore this policy does not report it:

my %hash = (__PACKAGE__   # ok, expands
            =>
            'blah');

Whether writing that is a good idea is, um, a whole other conversation. πŸ‘€ It might be a bit subtle to depend on the newline. Probably a plain , comma would make the intention clearer than =>.

🧚 Class Data 🧚

A bad $obj->{__PACKAGE__} can pop up when you're trying to hang extra data on an object, using your package name in the hopes it won't clash with the object's native fields. An unexpanded __PACKAGE__ like that is a mistake you'll probably only make once; after that, the pure irritation of writing extra parens or similar will keep it fresh in your mind forever. 😭 Character development, honestly.

As usual there's more than one way to do it when you're associating extra data to an object. As a crib, here are some ways:

  • Subhash $obj->{(__PACKAGE__)}->{myfield} β€” the extra parens make sure it expands, and you get a sub-hash (or sub-array or whatever) all to yourself. It's easy to delete that single entry from $obj if/when you later want to clean up. 🧼
  • Subscript $obj->{__PACKAGE__,'myfield'} β€” this makes entries in $obj, with the $; separator emulating multidimensional arrays/hashes (see "$;" in perlvar).
  • Concated key $obj->{__PACKAGE__.'--myfield'} β€” again entries in $obj, but the key is formed by concatenation and an explicit unlikely separator. The advantage over , is that the key is a constant (after constant folding), instead of a join on every access, because $; could change. Iconic optimisation moment. πŸ”₯
  • Separate Tie::HashRef::Weak β€” use the object as a hash key and the value can be whatever data you want to associate. Keeps completely out of the object's hair, and also works with objects which use a "restricted hash" (see Hash::Util) to prevent extra keys.
  • Inside-Out Hash::Util::FieldHash β€” similar to HashRef, with the object as key and any value you want as the data outside the object, hence the jargon "inside out". The docs are very hard to follow (as of its version 1.04), especially if you're not into OOP, but it's actually fairly simple. Trust. πŸ¦‹
  • Scalar::Footnote β€” key/value pairs attached to an object using its "magic" list. Doesn't touch the object's contents, but separate footnote users must be careful not to let their keys clash. Play nice, babes.

🌈 SEE ALSO 🌈

Perl::Critic::Pulp, Perl::Critic, "Special Literals" in perldata

πŸ”— HOME PAGE πŸ”—

http://user42.tuxfamily.org/perl-critic-pulp/index.html

Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde

Perl-Critic-Pulp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

Perl-Critic-Pulp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.


πŸ’– Okay that's the whole page bestie, go forth and write the quotes, it's giving clarity and the vibes are immaculate. πŸ’–

mwah πŸ’‹ this was served up with perl v5.40.1, dated 2025-10-21 β€” no cap, that's the version and the date, and I'm obsessed. πŸŽ€βœ¨

πŸ“¦ where this page comes from