[sf-perl] Re: [oak perl] print Dumper \$|;

Belden Lyman blyman at iii.com
Thu Jan 16 11:20:18 CST 2003


qw at sf.pm.org wrote:
> Oops, I forgot to CC Oakland.pm.  Please reply-all to this message,
> not the previous one, to include them.


Let's blame the OP for being a cross-posting lame-o.
Oh, wait, that's me. Well, still. :)

> 
> That's confusing.  I first thought maybe $| was a tied variable, which
> would explain this behavior.  So, I tried doing 'tied $|' to see what
> it was tied to.  The result was undef--meaning it's not a tied.  But,
> wait, 'tied %ENV' also returns undef.  Does anyone know why?  Is this
> a bug?  (All of this is in Perl 5.6.1 on Solaris.)
> 

I think $| manages to achieve its boolean magic without using tie.
But this is just a guess based on your test.


> Anyway, I guess the larger moral of this story is that $| has a
> Boolean value, and you should only think of it in terms of true
> (nonzero) or false (zero), and not do math operations on it.  Why
> would you want to increment $|, anyway?
> 

    $| = 1;   # autoflush pipes
    $|++;     # same as $| = 1;

    $| = 0;   # umm, clog pipes
    $|--;     # same as $| = 0;

What's neat is that you can $|++ all you want, but the highest value
that $| will ever have is 1; similarly, you can $|-- all you want,
but it'll always be ...

And it's the ... that I was trying to get Data::Dumper to tell me:
I expected to see either 0 or undef as the value for $|--, but instead
saw 1.

The reason I even care about this is that I like having the option to
toggle $| either by setting it directly or by (in|de)crementing it.
More to the point, I like this option so much that yesterday I wrote
up Tie::Boolean that allows one to stuff like this:

     package Person;

     use Tie::Boolean;

     sub new {
       my (
           $invocant,
           %args,
          ) = @_;

       my $class = ref $invocant || $invocant;

       my $self = \%args;
       tie $self->{effusive}, q/Tie::Boolean/, 0;

       bless $self, $class;

       $self->effusive++ if $self->{job} =~ /sales/i;

       return $self;
     }

     sub effusive : lvalue {   # lvalue is experimental
       my $self = shift;
       $self->{effusive};      # don't use return
     }

     sub introduce {
       my $self = shift;

       if ( $self->effusive ) {
         print "Salutations! Greetings! Avast, matey!\n";
       }

       print "My name is ", $self->{name},
             " and I am a ", $self->{job},
             "\n";
     }

     package main;

     my $resident = Person->new( name => 'Betty Rubble',
                                 job => 'Comptroller', );

     my $salesman = Person->new( name => 'Fred Flintstone',
                                 job => 'Encyclopedia Salesman' );


     $salesman->introduce();   # he's in sales, he's effusive
     $resident->introduce();   # she's not in sales, not effusive

     $salesman->effusive--;    # make him more guarded
     $resident->effusive++;    # make her more effusive

     $salesman->introduce();   # they meet again!
     $resident->introduce();

     exit;

See, being able to do:

    $resident->effusive++;

gives me two things:

1. It saves me a whopping 1 keystroke:

    $resident->effusive(1);    # old, set explicitly
    $resident->effusive++;     # new

    (Of course, either of these invocations would work.)

2. But I'm really not much of a golfer, so I actually don't care
    about shaving off 1 keystroke. The big gain for me is that
    effusive() doesn't have to care what data it's being handed.

Internally, Tie::Boolean represents true as (surprise) 1 and false
as (surprise again) 0. At the end of the day yesterday I had a crisis
of correctness: should false be zero, or undef, or an empty string?

So I tried asking Data::Dumper the value of --$|, and got right
confused when Dumper thought --$| was the same as ++$|.

Oh, in the end, I decided to use 0 for false: the module is
called Tie::Boolean, not Tie::Defined.

Thanks to anyone who read this far.

Belden




More information about the Oakland mailing list