Fit to Be Tied (Tied Handles and Localized $\)

Jan 8, 2013 / By Yanick Champoux

Tags: ,

This one was going to be a cry for help and a request to confirm that I’m not going cuckoo, but I think I figured it out. Still, for giggles, hear this…

I was playing around with one of my favorite Himalayan barbershops (Galuga, one of those projects that just generate endless yak shaving) when I noticed something funny with tied filehandles. After much head-scratching, I was able to corner the problem with this small example:

use 5.10.0;

use strict;
use warnings;

{
    package Foo;

    sub TIEHANDLE { return bless my $i, shift; }

    sub PRINT { shift; $::X .= join '', @_, $; }

}

say "this is perl $]n";

print '>>>';
print "nothing here-->";
say   "but a CR there->";
print "and nothing here->";
print '<<<';

tie *::FOO, 'Foo';

print "nn";
print FOO "nothing here-->";
say   FOO "but a CR there->";
print FOO "and nothing here->";
print '>>>', $::X, '<<<';

$ = '';
$::X = '';

print "nn";
print FOO "nothing here-->";
say   FOO "but a CR there->";
print FOO "and nothing here->";
print '>>>', $::X, '<<<';

Basically, I defined a package that will act like a filehandle. The $ used in its PRINT is, according to perltie, the magic way to make sure print and say will both work. In the case of a say, $ will be localized and assigned a carriage return. Sounds good, no? But let’s see what happens when we run this baby:

$ perl fit_to_be_tied.pl
this is perl 5.014002

>>>nothing here-->but a CR there->
and nothing here-><<<

Use of uninitialized value $ in join or string at tie.pl line 13.
>>>nothing here-->but a CR there->
and nothing here->
<<<

>>>nothing here-->but a CR there->
and nothing here-><<<

The first stanza using STDOUT looks okay, but for the second stanza the print after the say seems to cling to having $ = "n" even if it’s not supposed to. And to add a dash of uh? to the whole thing, if we set the global ‘$’ not to be undef (as we did in the third stanza), all is fine again.

Fortunately, and thanks to perlbrew, I have a perl 5.17.6 lying around, and if I try the same test with it, I get:

$ perl fit_to_be_tied.pl
this is perl 5.017006

>>>nothing here-->but a CR there->
and nothing here-><<<

Use of uninitialized value $ in join or string at tie.pl line 13.
Use of uninitialized value $ in join or string at tie.pl line 13.
>>>nothing here-->but a CR there->
and nothing here-><<<

>>>nothing here-->but a CR there->
and nothing here-><<<

Well, look at that. Everything’s now behaving the way it should. I quickly perused the perldeltas since 5.16.1 (where the issue can also be seen) but didn’t notice any bug fix that could account for the change of behavior. Mind you, even then I won’t complain. I’ll just have one more reason to wait for 5.18.0 with bated breath…

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>