develooper Front page | perl.perl5.porters | Postings from January 2008

Re: "strict refs" not strict enough

Thread Previous | Thread Next
From:
Gerard Goossen
Date:
January 2, 2008 08:25
Subject:
Re: "strict refs" not strict enough
Message ID:
20080102162900.GM5329@ostwald
I was planning to do this in kurila. Already started by not allowing
stringification of GLOBs (which actually is a bit more difficult, 
because there are situation where GLOB stringification works). 

The only place where stringification is really needed is for debugging
and error message. There I find that having a function
doing quoting (properly reporting undef etc), more useful. A bit like the
Perl6 'perl' function (but without printing derefering etc). I am not
sure about the name, I don't like 'perl' very much, my current choice is
'view' but I don't like that very much either. (kurila also does '{' 
interpolating making calling the function easier, like "bla {view($arg)}")


On Fri, Dec 28, 2007 at 03:08:33AM -0500, Mark Jason Dominus wrote:
> 
> 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.
> 

-- 
Gerard Goossen
TTY Internet Solutions


Thread Previous | 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