develooper Front page | perl.perl5.porters | Postings from February 2022

The explicit strict hints bits - Can we remove them?

Thread Next
From:
Paul "LeoNerd" Evans
Date:
February 3, 2022 22:23
Subject:
The explicit strict hints bits - Can we remove them?
Message ID:
20220203222313.3dcd1d8c@shy.leonerd.org.uk
Before I get onto my actual point, let me paint a picture that is a
convenient lie, told through rose-tinted spectacles. It is not
completely true, but imagine in some future version of perl where the
`use builtin` feature becomes stable:

.oO(

    As well as performing a version check against the version of
    the currently-running perl interpreter, the `use VERSION` syntax is
    also a convenient shortcut for enabling a number of pragma modules.
    A `use VERSION` of any version equal to or greater than:

       v5.12 - implies a corresponding  use strict
       v5.34 - implies a corresponding  use warnings
       v5.10 - implies a corresponding  use feature ':VER'
       v5.38 - implies a corresponding  use builtin ':VER'

    where ":VER" is comprised of the major.minor parts of the
    fully-specified VERSION number.

    Thus, beginning your file with the line

       use v5.40.2;

    is equivalent to

       use strict;
       use warnings;
       use feature ':5.40';
       use builtin ':5.40';

)Oo.

Unfortunately, this would-be neat and tidy mental model is complicated
by the way that VERSION vs `strict` actually interact in practice.

See, `use v5.12` doesn't do exactly the same as `use strict`. While it
does enable the three strictness checks (refs, subs, vars), it does this
in a way that it remembers it did so in this indirect implied way. This
becomes visible the moment you try to `use VERSION` of some version
number smaller than 5.12 afterwards. At this point it turns off the
strictness flags that were not otherwise enabled by an explicit
`use strict`. For example:

    use v5.12;
    use strict 'vars'; # technically redundant here

    # At this point, all three strictures are turned on

    use v5.8;

    # At this point, the implicit strict subs and refs are turned off
    # but the explicit strict subs is still in effect.

This behaviour is unique to the `strict` pragma, and does not apply to
warnings, feature bundles, or the hypothetical builtin bundles we may
one day add. Even if you explicitly `use feature`, any enabled features
are reset by a subsequent `use v5.8`:

  $ perl -e 'use feature "say"; say "Hello"; use v5.0; say "Goodbye"'
  String found where operator expected at -e line 1, near "say "Goodbye""
          (Do you need to predeclare say?)


((Warnings behave in yet a third way - while a `use VERSION` of any
  version number v5.36 will enable `use warnings`, a subsequent version
  request for a smaller number will *not* disable it:

    $ ./perl -e 'use v5.35.9; use v5.8; my $x = 1 + undef'
    Use of uninitialized value in addition (+) at -e line 1.

  But this is not the subject of my current point; we should address
  that another day))


The reasons I mention all this are two-fold:

  1) It is a complicated and weird mental model to try to explain to
     people, because it means that `use VERSION` is not *exactly*
     equivalent to a shortcut for instead writing out the various
     `use` statements on the other pragmata in full. It is harder to
     document and explain to users.

  2) It consumes an extra three of those most precious PL_hints bits,
     of which we are now in a deficit. We have none spare and we'd
     really like at least one or two back for some new useful features
     we wish to add.

I have had a go at placating the second of these reasons, by trying to
move those hints bits out into their own variable. I have a
work-in-progress branch which mostly does this, though a few tests
still fail:

  https://github.com/leonerd/perl5/tree/rehome-explicit-strict-hints

Even if I get the remaining tests to pass however, I'd be reluctant to
suggest merging it because it does not fix the first reason above
(that the model is IMHO-needlessly complicated), and it involves the
addition of another obscurely-used internal variable named
${^EXPLICIT_STRICT} purely for the reason of letting the pureperl
strict.pm gain access to another interpreter-internal variable.


I would much rather just remove the behaviour entirely.

We could get rid of the HINT_EXPLICIT_STRICT_* bits altogether, and
simply state that a `use VERSION` of any number 5.12-or-above is
*exactly* equivalent to `use strict`, or a number 5.10-or-earlier is
exactly `no strict`. This would let us simplify our implementation,
tests, and most importantly user-facing documentation around the `use
VERSION` syntax. And it would gain us three precious hints bits back for
other purposes.


Thoughts, anyone?

-- 
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About