in reply to Re: eval-blocks and Test::Builder
in thread eval-blocks and Test::Builder

Actually, the nearly-equivalent code is:
sub _get_self { my $reftype = Scalar::Util::reftype( $_[0] ); $reftype = '' unless defined $reftype; if ( $reftype eq 'ARRAY' ) { return tied( @{ $_[0] } || $_[0] } return $_[0]; }
(Your version misses the fact that 'ARRAY' is a legal classname and that the value returned from tied() is a blessed hashref which makes the _get_self() for DBM::Deep::Hash more complex.)

(Yes, my code could be shortened if I was able to use // for defined-or. That's a 5.10ism and DBM::Deep runs on practically every Perl version since 5.004, we think.)

I don't like that code for three reasons:

  1. It's 6 times longer and has at least twice the number of codepoints. This makes it at least 4 times harder to comprehend at a glance.
  2. Writing that code correctly to function in all cases is hard. I had to edit my version twice as I was writing this reply because I found edge cases.
  3. It assumes that $_[0] will never be something that wants to pretend it's an array using overload. For example, using Contextual::Return or some other magic.

By using an eval-block, you allow the item to behave the way it wants to behave, if it wants to behave that way, plus you let Perl worry about the edgecases. To get truly equivalent code would be about 40 lines and I don't think I could get it all correct. At that point, an eval-block is quicker.


My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Replies are listed 'Best First'.
Re^3: eval-blocks and Test::Builder
by fergal (Chaplain) on Feb 25, 2006 at 01:16 UTC

    I'm not familiar with DBM::Deep but are you really expecting to have a $_[0] that's a Contextual::Return object? If _get_self is a method in the DBM::Deep::Array package then I don't see how any of the edge cases you have catered for could actually happen.

      A couple of the features that we're working towards are subclassibility and multiple engines. Which means DBM::Deep::Array could be subclassed by something that masquerades as an array using Contextual::Return or some other class that overloads @{}. Why should I prevent that when I prefer to use code that ducktypes $_[0] vs. explicit-types it?

      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        Why should I prevent that...

        Because it leads to lots of debugging and meditations about unexpected pitfalls :)

        Another possibilty is to create DBM::Deep::Array::Tied and bless tied arrays into that and untied into DBM::Deep::Array. Then you get 2 _get_self()s both of which are crystal clear.