develooper Front page | perl.perl5.porters | Postings from December 2007

"strict refs" not strict enough

Thread Next
From:
Mark Jason Dominus
Date:
December 28, 2007 00:08
Subject:
"strict refs" not strict enough
Message ID:
20071228080833.9580.qmail@plover.com

I have been thinking about this for a long time, and it has often
seemed to me that "strict refs" was not as helpful as it could be.


SUMMARY

1. The real problem that "strict refs" solves is accidental conversion
   of references to strings.  But it solves it in a kind of stupid way.

2. There are very few plausible uses for such conversions anyway.

3. Converting a reference to a string should raise a fatal error, except:
   a. When the converted string is immediately used as a hash key, or
   b. When the conversion is explicitly performed by a special
      "ref2string" function 


DETAILED EXPLANATION (TL;DR)

The idea of "strict refs" is that some program might accidentally turn
a reference into a string, and then try to use the string as if it
were a reference anyway, with the result that data would be stored or
fetched from a variable with the ridiculous name "SCALAR(0x436c1d)" or
"Potato=HASH(0x265fd1)".  This happens pretty often, and is worth
defending against.  Typical code that does it looks like this:

        foo($ref);

        sub foo {
          my $arg = shift;
          bar("$arg");
        }

        sub bar {
          my $ref = shift;
          push @$ref, "blah";
        }

Since the spurious quotation marks in sub foo are a common beginner
error, the  ref-used-as-string-used-as-ref problem comes up pretty often.

But the big problem with "strict refs" is that it does not warn early
enough.  In the example above, the fatal error occurs in subroutine
"bar".  In the example above, the real problem is in subroutine "foo".
This could thousands of lines away from where the error really
occured, or it could be in a different module, and in practice it
often is.

I would like to suggest that the real problem here is that references
should not be implicitly converted to strings.  If converting a
reference to a string were a fatal error, many or most "strict refs" errors
would be caught much earlier, at the place they actually occurred,
instead of far away.

Conversely, there are very few legitimate reasons to convert a
reference to a string.  I can think of only three:

    1. For diagnostic and debugging output
    2. As hash keys in certain special applications
    3. Something weird I didn't think of

We would not like these uses to raise an exception when a reference is
converted to a string.

#1 and #3 could be solved by providing a trivial function,
"ref2string", which explicitly converts a reference to a string
without raising a fatal error.  So instead of this:

        my $obj = Doggie->new(...);
        warn "Manufactured object '$obj'";

one would have this:

        my $obj = Doggie->new(...);
        warn "Manufactured object '" . ref2string($obj) . "'";

#2 could be solved by making an exception: references will be
converted to strings when used as hash keys, without raising any
errors:

        my $obj = Doggie->new(...);
        $doggies{$obj} = $obj;       # No fatal error here

Maybe this situation is infrequent enough that we could demand that
people use ref2string here anyway:

        my $obj = Doggie->new(...);
        $doggies{ref2string($obj)} = $obj;       # No fatal error here

I don't know.

But I don't think any of these things would be hard to implement.        


CONCLUSION

I suppose this will be lost in the noise, but it has been bothering me
for years, and so I thought I should try.


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