Michael G Schwern wrote:
> 
> So I thought of a serious problem with part of this RFC.  The bit
> about using indirect object syntax...
>
> There's a nasty inconsistency there.  Consider the following.
> 
>     package Foo;
>     sub lock {
>         flock $_[0], LOCK_EX;
>     }
>     lock $trans{$var};
> 
> Normally, the Foo::lock() subroutine in the current package will be
> called. However, if %trans is a tied hash to a class which defines a
> lock() method (let's call it Lock::Ness) the meaning of the program
> radically and unexpectedly changes.

That's true. However, this is actually no different than the situation
currently with blessed objects. If the code was rewritten:

   sub lock { print "Hello!" }
   $trans = new Lock::Ness;   # ;-)
   lock $trans;   # $trans->lock

The lock method from the $trans object would be called, even though
there was a main::lock, because of the higher precedence and binding of
indirect objects.
 
> But this doesn't really win you much besides some syntactic sugar.
> Consider this code:
> 
>     lock $trans{$var};
> 
> What if %trans is not tied?  Then a lock() subroutine would have to be
> in scope

Well, again, this is the same idea behind indirect object syntax in the
first place, and many people don't like it for this reason. If you ran
this code:

   $r = new Class;

without first importing Class, you'd get an OO package warning, not a
"method main::new not defined" warning.

However, here in the tie case I think it actually gains you a lot more
than just sugar. Without this facility, you have to mix OO and tied
calls, which can result in several problems. One of them is the
"dangling references" problem with trying to untie a variable whose
object is still being used. Another is how to make this:

   tie @a, 'Matrix';
   push @a, $stuff;        # @a->PUSH($stuff)
   push @b, $stuff;        # CORE::push(@b, $stuff)

extensible. Right now, @a->PUSH will be called, and CORE::push(@b) will
be called. This is fine, but one function that isn't implemented in
terms of tie is sort. That is, if you call sort on a tied array, then
CORE::sort is always used, even if tied. But what if you want a really
specific sort routine that was only called if the variable was tied?
You're stuck, having to do something like this:

   if ( $o = tied(@d) ) {
      $o->sort;
   } else {
      sort(@d);
   }

This is the problem that the RFC is attempting to solve. So in this
case, the indirect object syntax actually buys a lot. It has some snags,
though, see my follow up to Michael Fowler for these...

-Nate

Reply via email to