On 7/1/05, Michael G Schwern <[EMAIL PROTECTED]> wrote:
> After talking with Ovid some in the kitchen I'm of the opinion that
> is_deeply() is currently doing the right thing and that these tests cannot
> go.  Largely it comes down to the Principle of Least Surprise.

I cant agree with this analysis. If you go down this route surprise abounds.

(From my earlier post)

is_deeply($x,$y);  #ok

$x->[0]{a}=1;
$y->[0]{a}=1;

is_deeply($x,$y);  #Surprise!

Thats a MUCH bigger surprise IMO. And a fatal one for anybody really
relying on is_deeply.
 
> Here's an example.  A user wants to test the results of some function that,
> in this situation, includes some duplicated data.  So they might construct
> their "expected" structure like so to save a little time:
> 
> my %thing = { foo => 42, bar => 23 };
> 
> my %expect = ( stuff => 23,
>                wiff  => \%thing,
>                wham  => \%thing
>              );

As I think ive seen you do elsewhere just tell them NOT to do that.
What they should do is simple:

 my %expect = ( stuff => 23,
                wiff  => {%thing},
                wham  => {%thing}
              );

IMO this is a perfectly acceptable requirement.

> 
> Internally the code might not reuse the same reference.  The user would be
> very surprised if the comparison failed. 

Well i can see two cases for surprise, the majority would be
programmers going doh, of course they arent the same, and the minority
being the ones pleasently surprised that we had just caught a bug they
hadnt noticed before.

> In fact, I would even argue that
> this violates some of the black boxness of the test.  In much the same way
> that we don't check to see if a given piece of data is blessed, tied or
> overloaded, we wouldn't care if we have a repeating reference or two
> different references to equivalent data.

But they COMPLETELY change the datastructure. Utterly and totally. 

The question you have to ask yourself is why should a reference be
treated different from any other value? It is a VALUE.
IE: why should

$x=1;$y=2;$z=3;

$a1=[$x,$x];
$a2=[$y,$z];

$a1 and $a2 are different but

$x={};$y={};$z={};

$a3=[$x,$x];
$a4=[$y,$z];

$a3 and $a4 are not? Isn't the situation identical? Consider

# add one to each of the arrays
for my $ar ($a1,$a2,$a3,$a4) {
  $_=0+$_ @$ar;
}

so now the refs turn into their addresses and you will consider them
different? This just doesnt make sense.


> 
> Furthermore, the current behavior provides the more flexible option.  If
> a user doesn't care about the particulars of the references in their
> structure, is_deeply() works.  

If they dont care then they should use some other tool beside
is_deeply(). maybe a new sub called looks_like() or something, but
is_deeply should be reliable and do what its name says.

The fact is it wouldnt be too difficult to support both off of the
same code base. It would just be a flag into the internal routine.

> If they *do* then the user can always run
> an addition test.  But if we made is_deeply() repeating reference aware then
> the user who does not care about that cannot use is_deeply() at all.
> 
> So, I conclude that is_deeply()'s behavior is ok and something like Test::Deep
> should be enhanced with an option to deal with this problem.

Ok, ill make my last defense.

For this decision you gain what?

You gain a saving of ONE KEYSTROKE.  (instead of being lazy and saying
\%obj you say { %obj } ).

What do you lose?

The ability to use this routine safely at all. The only people that
will be able to use this routine wont actually be doing deep
comparisons.  Not only that you propogate a bad meme, that is_deeply
does deep structural comparison when it doesnt.  This means that lots
of users out there think that if two structures are is_deeply() then
they are equivelent, little do they know of course that arent
_at_all_.

I personally feel that the Test modules have a duty or obligation to
not propagate mistaken understandings in the community. is_deeply()
should be robust and reliable. It should be a standard bearer for the
community.  Making is_deeply() behave in such a broken behaviour is
just bad for Perl in general. And for such little advantage?

IMO if people want a tool like you think is_deeply() should behave
then you should provide one. But dont pretend is_deeply() does a deep
comparison when it really doesnt. Referential integrity of the
structural comparison should be just as important as the value
comparision as this data can be vital to complex programming tasks.

Im happy to do the work to fix is_deeply() and also to provide
looks_like(). I do not think this should be in another module as the
amount of code change to what you have is pretty minimal.

-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

Reply via email to