diotalevi has asked for the wisdom of the Perl Monks concerning the following question:

I would like the following code to be a fatal error. How do I do this?

$ref = \ $var; "$ref"
$ref = \ $var; print $ref;

theorbtwo had a suggestion but it only covers stringifying blessed references.

package UNIVERSAL; use overload q("") => sub { die "Attempt to stringify reference" };

Replies are listed 'Best First'.
Re: How to prevent references from stringifying?
by xmath (Hermit) on Oct 03, 2004 at 14:57 UTC
    I just checked the perl source. I don't see any way of doing this for general references without patching perl. The good news is that's it's easy to patch, so if you're comfortable with recompiling your perl to debug your problem, it's an option.

    For perl 5.8.5:

    --- sv.c.org 2004-07-12 23:44:41.000000000 +0200 +++ sv.c 2004-10-03 16:54:08.000000000 +0200 @@ -3126,2 +3126,3 @@ } + Perl_croak(aTHX_ "Stringification of reference disallowed"); tsv = NEWSV(0,0);

    This still allows stringification of compiled regexen, or when overloading is in place. If you want to disallow stringification in those cases too (so, for all references), you can instead do:

    --- sv.c.org 2004-07-12 23:44:41.000000000 +0200 +++ sv.c 2004-10-03 16:56:34.000000000 +0200 @@ -3001,2 +3001,3 @@ SV* tmpstr; + Perl_croak(aTHX_ "Stringification of reference disallowed"); if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,string)) &&

    UPDATE: Just in case you're unfamiliar with applying a patch: unpack the perl 5.8.5 source, save one of the above snippets as "patchfile", execute (in the unpacked perl dir) the following command: patch < path/to/patchfile and then compile perl normally

•Re: How to prevent references from stringifying?
by merlyn (Sage) on Oct 03, 2004 at 15:49 UTC
    I write code that counts on references being able to stringify. If you turn that off, don't count on being able to use my modules.

    What I'm saying is beware of doing anything global - you may be breaking someone else's code.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      If you s/Perl_croak/Perl_warner/ in the patches above then you can make it a warning, rather than a fatal. Then you can install a signal handler to deal with it as desired. Nothing should break, although things might get a bit noisy.

      Perl_warner( aTHX_ WARN_SYNTAX, "Stringified reference\n" ); /* or you could make references REALLY strict ;-) */ if ( PL_hints & HINT_STRICT_REFS ) Perl_croak( aTHX_ "Stringification of reference disallowed\n" );

      It looks like it is pretty easy to add a new item to strict as well. *Untested* there appear to be only 3 modifications required. The PL_hints var contains a number of hints set at compile/runtime. The hints are accessed via HINT_ constants set in perl.h There are plenty of spare mask bits. 0x04 is documented as unused so you could

      /* in perl.h with the rest of the HINT_ defines */ + #define HINT_STRICT_STRINGIFY 0x00000004 /* in sv.c as noted by xmath */ + if ( PL_Hints & HINT_STRICT_STRINGIFY ) + Perl_croak(aTHX_ "Stringification of reference disallowed"); # in strict.pm my %bitmask = ( + stringify => 0x00000004, refs => 0x00000002, subs => 0x00000200, vars => 0x00000400 ); sub bits { my $bits = 0; foreach my $s (@_){ $bits |= $bitmask{$s} || 0; }; $bits; } sub import { shift; - $^H |= bits(@_ ? @_ : qw(refs subs vars)); + $^H |= bits(@_ ? @_ : qw(refs subs vars stringify)); } sub unimport { shift; - $^H &= ~ bits(@_ ? @_ : qw(refs subs vars)); + $^H &= ~ bits(@_ ? @_ : qw(refs subs vars stringify)); }

      As you can see you could leave strict alone and just doe $^H |= 0x00000004 to set it.

      cheers

      tachyon

        Actually, PL_hints is just used at compile-time, not at runtime. But using (PL_curcop->op_private & HINT_STRICT_STRINGIFY) instead should work.

        UPDATE: Oh, and a minor note: Perl_warner needs an additional argument that indicates the warning category, like:

        if ((PL_curcop->op_private & HINT_STRICT_STRINGIFY) && ckWARN(WARN_MISC)) Perl_warner(aTHX_ packWARN(WARN_MISC), "Stringification of reference disallowed");
        or alternatively you could omit the check and use Perl_warn which takes no such argument.
Re: How to prevent references from stringifying?
by ikegami (Patriarch) on Oct 03, 2004 at 02:06 UTC
    Do you want this to work for all file handles or just STDOUT? You could replace STDOUT with a tied object which checks for references.
      I would like this to happen against general stringification. I used print as an example. I could have said "$ref". I'm getting files named SCALAR(0x....) in my home directory and I don't know why.
Re: How to prevent references from stringifying?
by Arunbear (Prior) on Oct 03, 2004 at 14:55 UTC
    If tie is allowed, then combining theorbtwo's idea with an unorthodox tie seems to work:
    use strict; use warnings; $|++; package NoStringify; use Tie::Scalar; use Carp; our @ISA = ('Tie::StdScalar'); use overload q("") => sub { croak "Attempt to stringify reference" }; sub FETCH { # return $self rather than $$self ! my $self = shift; } package main; my $var = 10; my $ref = \$var; tie $ref, 'NoStringify'; my $val = $$ref; print "$val\n"; print $ref; __END__ Output: 10 Attempt to stringify reference at ...
Re: How to prevent references from stringifying?
by Jenda (Abbot) on Oct 03, 2004 at 18:58 UTC

    I think you might be able to do it using autobox and overload. Something like this I think:

    package REF; use overload q("") => sub { die "Attempt to stringify reference" }; package main; use autobox 'REF' => 'REF', DEFAULT => undef; ...
    You need at least perl 5.8.1 for this though. That's why I can't test the code myself. (I should update one of these days ...)

    Jenda
    We'd like to help you learn to help yourself
    Look around you, all you see are sympathetic eyes
    Stroll around the grounds until you feel at home
       -- P. Simon in Mrs. Robinson

      I just took a quick look at autobox, and in particular the patch it requires to be applied to perl... It seems it only enables method calls on non-objects, but it does not appear to extend other object-qualities such as overloading to non-objects.

      So this trick wouldn't work afaict.