Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-02 Thread A. Pagaltzis
* Michael G Schwern <[EMAIL PROTECTED]> [2007-03-02 22:35]:
> Joshua ben Jore wrote:
> > Does defined( Scalar::Util::blessed )have cooties? Its the
> > only predicate you've ever had that actually works.
> 
> It requires depending on an XS module if you want compatibility
> pre-5.8.1.

Which is the Perlish equivalent of having cooties, I guess. :-)

Regards,
-- 
Aristotle Pagaltzis // 


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-02 Thread Michael G Schwern
Joshua ben Jore wrote:
> Does defined( Scalar::Util::blessed )have cooties? Its the only
> predicate you've ever had that actually works.

It requires depending on an XS module if you want compatibility pre-5.8.1.
I have to worry about stuff like that.


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-02 Thread chromatic
On Friday 02 March 2007 08:27, Joshua ben Jore wrote:

> Does defined( Scalar::Util::blessed )have cooties? Its the only
> predicate you've ever had that actually works.

Sometimes I want to detect class methods too.

Y'know, at some point it's worth saying "Here's how this works.  Here are the 
reliable ways to answer these questions.  If someone does something really 
stupid, their code will break.  Let it."

I remember patching the documentation for this somewhere.

-- c


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-02 Thread Joshua ben Jore

On 3/2/07, Michael G Schwern <[EMAIL PROTECTED]> wrote:

Eirik Berg Hanssen wrote:
> Michael G Schwern <[EMAIL PROTECTED]> writes:
>
>> chromatic wrote:
>>> On Thursday 01 March 2007 17:46, Adam Kennedy wrote:
>>>
 Actually, isn't UNIVERSAL::can($x, 'can') still valid? I seem to
 remember that at one point it was considered the only valid use of
 UNVERSAL::can directly.
>>> That's the only case I can think of too.
>> Hmm, that's a clever way of determining if something is an object.
>>
>> I guess UNIVERSAL::isa($thing, "UNIVERSAL") works, too.  And
>> UNIVERSAL::can($thing, "isa").
>
>   Not so if your $thing is a non-object sting that happens to be a
> package name ...

Oh yeah.  I guess it would have to be C<< ref $thing &&
UNIVERSAL::isa($thing, "UNIVERSAL") >>.

And the first person to point out it doesn't work if $thing is blessed into
class "0" gets their face dunked in pancake batter and fried.


Does defined( Scalar::Util::blessed )have cooties? Its the only
predicate you've ever had that actually works.

Josh


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-02 Thread Michael G Schwern
Eirik Berg Hanssen wrote:
> Michael G Schwern <[EMAIL PROTECTED]> writes:
> 
>> chromatic wrote:
>>> On Thursday 01 March 2007 17:46, Adam Kennedy wrote:
>>>
 Actually, isn't UNIVERSAL::can($x, 'can') still valid? I seem to
 remember that at one point it was considered the only valid use of
 UNVERSAL::can directly.
>>> That's the only case I can think of too.
>> Hmm, that's a clever way of determining if something is an object.
>>
>> I guess UNIVERSAL::isa($thing, "UNIVERSAL") works, too.  And
>> UNIVERSAL::can($thing, "isa").
> 
>   Not so if your $thing is a non-object sting that happens to be a
> package name ...

Oh yeah.  I guess it would have to be C<< ref $thing &&
UNIVERSAL::isa($thing, "UNIVERSAL") >>.

And the first person to point out it doesn't work if $thing is blessed into
class "0" gets their face dunked in pancake batter and fried.


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-02 Thread Eirik Berg Hanssen
Michael G Schwern <[EMAIL PROTECTED]> writes:

> chromatic wrote:
>> On Thursday 01 March 2007 17:46, Adam Kennedy wrote:
>> 
>>> Actually, isn't UNIVERSAL::can($x, 'can') still valid? I seem to
>>> remember that at one point it was considered the only valid use of
>>> UNVERSAL::can directly.
>> 
>> That's the only case I can think of too.
>
> Hmm, that's a clever way of determining if something is an object.
>
> I guess UNIVERSAL::isa($thing, "UNIVERSAL") works, too.  And
> UNIVERSAL::can($thing, "isa").

  Not so if your $thing is a non-object sting that happens to be a
package name ...

[EMAIL PROTECTED]:39:06]~$ perl -le '$thing = "main"; print for 
UNIVERSAL::can($thing, "isa"), UNIVERSAL::isa($thing, "UNIVERSAL"), eval { 
$thing->UNIVERSAL::can("can") }'
CODE(0x8130278)
1
CODE(0x81302b4)
[EMAIL PROTECTED]:39:18]~$ 

  Sorry; I got nothing.

Eirik
-- 
All bridge hands are equally likely, but some are more equally likely
than others.
-- Alan Truscott


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-01 Thread Michael G Schwern
chromatic wrote:
> On Thursday 01 March 2007 17:46, Adam Kennedy wrote:
> 
>> Actually, isn't UNIVERSAL::can($x, 'can') still valid? I seem to
>> remember that at one point it was considered the only valid use of
>> UNVERSAL::can directly.
> 
> That's the only case I can think of too.

Hmm, that's a clever way of determining if something is an object.

I guess UNIVERSAL::isa($thing, "UNIVERSAL") works, too.  And
UNIVERSAL::can($thing, "isa").


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-01 Thread A. Pagaltzis
* Adam Kennedy <[EMAIL PROTECTED]> [2007-03-02 03:05]:
> This will hopefully clear up the Module::Build bootstrap
> problem and remote the need for Module::Install altogether
> (other than as syntactic sugar).

Best Perl-related news I’ve seen in a while.

Regards,
-- 
Aristotle Pagaltzis // 


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-01 Thread chromatic
On Thursday 01 March 2007 17:52, Adam Kennedy wrote:

> As much as I dislike UNIVERSAL::, I'd FAR prefer to have it all
> maintained by one person.
>
> That way I can submit my typically evil bugs in Test::MockObject and
> have chromatic do whatever is needed across all the modules to make it
> work.

I'm also nearly to the point where UNIVERSAL::isa and UNIVERSAL::can are 
almost but not quite the same code.  That's a *very* nice feature when 
dealing with something this potentially fragile.

(Plus if they can give per-object warnings, it sounds like a lot of people 
will be happier.)

> As much as we disagree (violently sometimes) on a number of issues,
> chromatic++ for fixing all my bugs in Test::MockObject.

You wacky Australians and your crazy ideas of violence!

-- c


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-01 Thread chromatic
On Thursday 01 March 2007 17:46, Adam Kennedy wrote:

> Actually, isn't UNIVERSAL::can($x, 'can') still valid? I seem to
> remember that at one point it was considered the only valid use of
> UNVERSAL::can directly.

That's the only case I can think of too.

-- c


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-01 Thread Adam Kennedy

chromatic wrote:

On Monday 26 February 2007 06:35, Christopher H. Laco wrote:


Or me. I have a personal hate relationship with MockObject in this way.
I love MockObject. I hate getting warnings about 3 party modules use of
can in my test suite.


Ideally those third parties would fix their buggy code, but after countless 
messages, a couple of articles, and a couple of years of saying "If you're 
going to write OO code, at least pretend to support objects", I'm not sure if 
it's working.


I think we've hit the same problem/limit with Module::Install. The 
assumption that authors will update/repair their code within a 5 year 
transition period is not valid it seems, even with strong education.


At the moment, I'm working around the specific case of TT by local'ly 
disabling warnings globally before calling TT methods, and trying to 
restrain myself from using my co-maint to just add a dependency on 
Params::Util and fix it.


As for the toolchain problem I plan to just knuckle down, kick some 
heads, and fix the toolchain properly between 5.10.0 and 5.10.1. Mostly 
these fixes will look like very small things. The first is the addition 
of CPANPLUS_IS_EXECUTING from last week.


This will hopefully clear up the Module::Build bootstrap problem and 
remote the need for Module::Install altogether (other than as syntactic 
sugar).


Adam K


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-01 Thread Adam Kennedy

Yuval Kogman wrote:

On Sun, Feb 25, 2007 at 22:34:15 -0800, chromatic wrote:


Why not, I already have half of the other stuff in UNIVERSAL


Just don't tell Adam.


As much as I dislike UNIVERSAL::, I'd FAR prefer to have it all 
maintained by one person.


That way I can submit my typically evil bugs in Test::MockObject and 
have chromatic do whatever is needed across all the modules to make it work.


As much as we disagree (violently sometimes) on a number of issues, 
chromatic++ for fixing all my bugs in Test::MockObject.


Now I just need to try and replicate this last evil case that 
demonstrates why/when UNIVERSAL::isa/can break because they aren't 
re-entrant.


Adam K


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-03-01 Thread Adam Kennedy

Yuval Kogman wrote:

BTW, pure perl blessed() will work:

sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }

sub blessed ($) {
  local($@, $SIG{__DIE__}, $SIG{__WARN__});
  length(ref($_[0]))
? eval { $_[0]->a_sub_not_likely_to_be_here }
: undef
}



I predict that the next anti duck perl idiom is going to be:

eval { $x->UNIVERSAL::can("can") }

to determine "true blessedness" 



Actually, isn't UNIVERSAL::can($x, 'can') still valid? I seem to 
remember that at one point it was considered the only valid use of 
UNVERSAL::can directly.


Adam K


Re: Object Identification Cold War and the return of autobox.pm (was Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane)

2007-03-01 Thread Adam Kennedy

chromatic wrote:

On Monday 26 February 2007 13:50, Michael G Schwern wrote:


But what if isa() is broken or has side effects, hmm?


That's not the caller's problem.  Fix the broken code.  Don't break more code 
trying to work around bugs.


I think the problem he's refering to is that if the caller is using eval 
{ $obj->isa(...) } you won't get an error, because it got ignored.


It will just spurious return a false result, not an exception.

Adam K


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-28 Thread Joshua ben Jore

On 2/25/07, Joshua ben Jore <[EMAIL PROTECTED]> wrote:

I've hated it how ref() does the wrong thing so frequently so I wrote
a fix for it. I like to use mock objects to feed fake or proxy objects
to other things but this breaks when things not under my control use
ref() to examine the class of an object.

No longer. Under most circumstances ref() behaves normally. The only
time it lies is if you've requested it from a package and have a ref
method.


I tried adding this bit of code to Exception::NoException last night
and it highlighted the problem that even though I want to have a lying
object, it depends who is asking whether I want to lie or not.

 use UNIVERSAL::ref;
 sub ref { '' }

Exception::NoException is an overloaded object but now overload.pm
doesn't know that anymore and all the overloading breaks. Bummer.
Perhaps I could detect that the object uses overload and therefore it
shouldn't lie to it or perhaps I just declare across the board that
UNIVERSAL::ref doesn't lie to overload or better... I ask you all if
there's a better way to think of this.

overload.pm doesn't say CORE::ref() but that's what it really, truely
intends to say. I can't detect CORE::ref() vs ref() but that doesn't
matter anyway. So... I've got the job of somehow deciding when is an
appropriate time to call the hook or the real ref(). I'm not sure when
that is.

Any thoughts?

Josh


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-28 Thread Adrian Howard


On 26 Feb 2007, at 18:23, chromatic wrote:
[snip]
I'm open to a patch that allows people who know what they're doing  
to disable

the warnings.


Thank you!


Adrian said he might write one.

[snip]

I shall. I might even do it now :)

Adrian



Re: Object Identification Cold War and the return of autobox.pm (was Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane)

2007-02-27 Thread Michael G Schwern
Rafael Garcia-Suarez wrote:
> On 26/02/07, chromatic <[EMAIL PROTECTED]> wrote:
>> > Please reconsider autobox.
>>
>> I second this request.
> 
> autobox in on CPAN and works. Moreover, the intent of the work on
> lexical pragmas was to enable people to write their own pragmas and
> put them on CPAN. (*) So just use it.

Normally I would agree, I'm firmly in the "the only modules which should
ship with the core are those which help installing more modules" camp.  But
this seems a bit of fundamental language stuff that happens to be available
as a module.


> Or, maybe you were asking to make autobox the default ? No. That's not
> going to happen anytime soon. The implications for backwards
> compatibility are too huge.

Well, yes I was. :)  The last time it was discussed I don't recall much
consideration given to backwards compatibility.  Mostly it was that folks
didn't see much utility.

So what are the backwards compatibility implications?

One off the top of my head is code like this...

sub is_object {
my($thing) = shift;
return eval { $thing->isa("UNIVERSAL") };
}

But I wonder how many people do something like that, what its used for and
if anything would really break if everything were an object.


> And moreover the feature list for 5.10 is
> frozen (almost), because at some point we have to release.

Sorry, I didn't mean to imply squeezing it into 5.10.  Whether it makes it
into 5.10 or 5.12 or 5.14 is a whole other issue.  Right now I just want to
crack the discussion back open.


Re: Object Identification Cold War and the return of autobox.pm (was Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane)

2007-02-27 Thread Rafael Garcia-Suarez

On 26/02/07, chromatic <[EMAIL PROTECTED]> wrote:

> Please reconsider autobox.

I second this request.


autobox in on CPAN and works. Moreover, the intent of the work on
lexical pragmas was to enable people to write their own pragmas and
put them on CPAN. (*) So just use it.

Or, maybe you were asking to make autobox the default ? No. That's not
going to happen anytime soon. The implications for backwards
compatibility are too huge. And moreover the feature list for 5.10 is
frozen (almost), because at some point we have to release.

If autobox gets popular, used, stable, it might be included in perl
5.12 core. For the moment I think that's premature and I'd rather have
people adding it as a prerequisite of their modules. (Note that I hope
that 5.12 will happen in a much shorter range of time than we had to
wait between 5.8.0 and today for 5.10.)

(*) I note that autobox does some unclean hacks with $^H and %^H in
order to try to be lexical. That would cause problems in evals. I
think it will have to be rewritten for  recent perls, to use the new
lexical pragma capability.


Re: Object Identification Cold War and the return of autobox.pm (was Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane)

2007-02-26 Thread Yuval Kogman
On Mon, Feb 26, 2007 at 13:50:58 -0800, Michael G Schwern wrote:

> Please reconsider autobox.

While I second that for the aforementioned reasons I have an off
topic one too:

That's the only way it'd get accepted. Something that devious has to
be in core to pass off as safe.

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpY9mRjlwYl6.pgp
Description: PGP signature


Re: Object Identification Cold War and the return of autobox.pm (was Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane)

2007-02-26 Thread chromatic
On Monday 26 February 2007 13:50, Michael G Schwern wrote:

> But what if isa() is broken or has side effects, hmm?

That's not the caller's problem.  Fix the broken code.  Don't break more code 
trying to work around bugs.

That little mantra could have solved a whole lot of this mess.

> And what if its lying to me and I *really* want to know what methods are
> *really* available and not autoloaded?

Then you have at least two problems, and at least one of them is that you're 
using the wrong language.

> IT SHOULD NOT BE THIS COMPLICATED TO IDENTIFY THE HERITAGE OF AN OBJECT!

It should almost never be necessary to identify the heritage of an object.  
This ain't structural subtyping.  Perl 5.9.4 has UNIVERSAL::DOES() for a 
reason.

(To stave off all the "Buh... buh... but I used blessed hashes and I need to 
know if it's a hash!", I say "Keyed index overloading has worked for over a 
decade.  At some point it would be nice to be able to use it without people 
breaking my objects.")

> Please reconsider autobox.

I second this request.

-- c


Object Identification Cold War and the return of autobox.pm (was Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane)

2007-02-26 Thread Michael G Schwern
Yuval Kogman wrote:
>> Likewise with ref in boolean context, I almost never want the object
>> to be able to lie to me.
> 
> But if it has to work hard to lie, then does it matter?

Yeah, I'm with Yuval here.  There seem to be a cold war going on here wrt
identifying an object.

In the beginning we used UNIVERSAL::isa() and UNIVERSAL::can().  And it
could identify the nature of any scalar, blessed or not.  Reference or not.
 And it was good.

And then someone got clever and overrode isa() and can().  And there was
much wailing and nashing of teeth and slaughtering of lambs.  Now we're
supposed to use C<< eval { $obj->isa($class) } >> and for a while balance
was restored.

And then someone defined a $SIG{__DIE__} so now its C<<{ local
$SIG{__DIE__};  eval { $obj->isa($class) } }>> or you must depend on having
a 3rd party module written in XS, Scalar::Util, available and compiled and
do C>.

And then someone got really clever and blessed their object into class "0".
 Now we must do C>.  Or if you can't rely on Scalar::Util:  C<< local
$SIG{__DIE__};  eval { $obj->isa($class) } >>.

But what if isa() is broken or has side effects, hmm?  And what if its lying
to me and I *really* want to know what methods are *really* available and
not autoloaded?  And what if someone got even more clever and blessed into
class ""...

ARGHAGHAGHHHH!

IT SHOULD NOT BE THIS COMPLICATED TO IDENTIFY THE HERITAGE OF AN OBJECT!

The best practice should be straightforward:  Ask the object.  If it wants
to lie to you and override isa() or use class "0" (and yes, there really is
no other reason to use such a class name but to lie) then damned well let
it.  We call this "encapsulation" and it is good.

99.999% of the time you do not want to really know how something is
implemented, you want to remain ignorant.  It is detrimental for your
shopping cart code to pierce the facade surrounding the objects it is using.
 The remaining 0.001% of the time you're writing something like Data::Dumper
or a serialization module and fine, employ all the magic you like, but don't
try to apply the needs of a module like Data::Dumper to Joe Business
Programmer!  If I caught someone blessing into class "0" at my work he'd
have to give such a damned good reason that I wouldn't use his eye sockets
for USB ports.

All the trouble here seems to stem from the fact that its so damned hard to
reliably determine what is and is not an object.  And the only reason we
care about that is so we can call isa() on it.  The proper way to identify
the nature of an object is C<< $obj->isa($class) >>.  The proper way to
identify whether a class has a method is C<< $obj->can($method) >>.  Done.
All the other junk we do these days is determining if its blessed so there's
not an error when we try to call a method on it.

Solution... make everything an object.  Or at least everything callable with
methods.  Or for bloody screaming hell at least the UNIVERSAL ones!  This is
called "autoboxing" and there's already a module out there to do it.
http://search.cpan.org/dist/autobox.  In one fell swoop all this nonsense
goes away.  It doesn't even require a core patch anymore.

$ perl -Mautobox -wle 'print []->isa("ARRAY");'
1

autobox.pm was proposed as a core module many moons ago but it was rejected
as not being necessary.  As its a central tenet of any decent OO language
that everything should be (or at least act like) an object I was very
dismayed at that.  Well, here's your use case.

Please reconsider autobox.


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread chromatic
On Monday 26 February 2007 06:35, Christopher H. Laco wrote:

> Or me. I have a personal hate relationship with MockObject in this way.
> I love MockObject. I hate getting warnings about 3 party modules use of
> can in my test suite.

Ideally those third parties would fix their buggy code, but after countless 
messages, a couple of articles, and a couple of years of saying "If you're 
going to write OO code, at least pretend to support objects", I'm not sure if 
it's working.

I'm open to a patch that allows people who know what they're doing to disable 
the warnings.  Adrian said he might write one.

-- c


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Yuval Kogman
On Mon, Feb 26, 2007 at 18:22:21 +0100, demerphq wrote:

> I am. Actually my view is that using ref at all unless you control the
> input is an error.

Code like Data::Visitor does not need to be as low-level-true as
e.g. Data::Dump::Streamer, but still has to polymorphically handle
objects, refs and non refs. That's a valid case, IMHO.

> Too many times ive bumped into dumbass code that does
> 
> if (ref($ob) == 'ARRAY') {...}
> 
> so that i cant pass an object into the routine, for no good reason at all.

That's not good code, but it's wrong for other reasons

> Likewise with ref in boolean context, I almost never want the object
> to be able to lie to me.

But if it has to work hard to lie, then does it matter?

> Well i am biased in that ive spent a ton of time on data serialization
> modules where i never want to be lied to.

Right, in that specific case treating the return value from ref as a
boolean is an error, but in "standard" code"?


> If i dont care what the object is or whether they passed in an object
> then i wont test for it at all.
> 
> Turning this around for a moment, when does it make sense to use ref
> and yet at the same time not care that it might lie?

Like yours, most of my code that shouldn't care at all what the
value wouldn't contain a ref() or blessed() anywhere...

But there is code in between serializer level omniscience and
generic code level indifference - there's lots of code that needs to
care a little bit in order to be more flexible, not less. I can post
examples of what I mean if you like.

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpNy7KmpcDAD.pgp
Description: PGP signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread demerphq

On 2/26/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:

On Mon, Feb 26, 2007 at 17:47:23 +0100, demerphq wrote:
> On 2/26/07, Joshua ben Jore <[EMAIL PROTECTED]> wrote:
> >I'm of the opinion that it is clear and blatantly an error to ever use
> >ref as a boolean.
>
> One liners and minor snippets where you control the input data would
> be an exception IMO.


Are you guys serious?


I am. Actually my view is that using ref at all unless you control the
input is an error.

Too many times ive bumped into dumbass code that does

if (ref($ob) == 'ARRAY') {...}

so that i cant pass an object into the routine, for no good reason at all.

Likewise with ref in boolean context, I almost never want the object
to be able to lie to me.


When has this ever been an issue in practice? The only time it has
been an issue the intended behavior was in fact that the object
really not be treated as an object (Scalar::Defer). Someone trying
to bless into these classes is obviously doing it for that intended
behavior.


Well i am biased in that ive spent a ton of time on data serialization
modules where i never want to be lied to.

If i dont care what the object is or whether they passed in an object
then i wont test for it at all.

Turning this around for a moment, when does it make sense to use ref
and yet at the same time not care that it might lie?

Yves

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


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Yuval Kogman
On Mon, Feb 26, 2007 at 17:47:23 +0100, demerphq wrote:
> On 2/26/07, Joshua ben Jore <[EMAIL PROTECTED]> wrote:
> >I'm of the opinion that it is clear and blatantly an error to ever use
> >ref as a boolean.
> 
> One liners and minor snippets where you control the input data would
> be an exception IMO.


Are you guys serious?

When has this ever been an issue in practice? The only time it has
been an issue the intended behavior was in fact that the object
really not be treated as an object (Scalar::Defer). Someone trying
to bless into these classes is obviously doing it for that intended
behavior.

What is the alternative? How much "broken" perl code do you intend
to fix?

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpxh861JJQV8.pgp
Description: PGP signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread demerphq

On 2/26/07, Joshua ben Jore <[EMAIL PROTECTED]> wrote:

I'm of the opinion that it is clear and blatantly an error to ever use
ref as a boolean.


One liners and minor snippets where you control the input data would
be an exception IMO.


The correct boolean is defined( blessed( obj ) ) because this returns
a true value for all objects regardless of goofy class name and a
false value for everything not an object. This is purely because
blessed() avoided ref()'s problem and used undef as its false value
and not ''. It is impossible to bless into undef and this makes
blessed() a better test.


I agree, blessed has the right behaviour, but only because '',"\0" and
0 are legal class names. reftype() however has no excuse for returning
undef as all the possible legal values are determined by core and will
never evaluate to false. But alas its a long time too late to change.


Although...

I also think there may be a difference between code that wants the
"common" truth and other code that wants the "real" truth. Dumping and
serialization code probably wants to avoid being lied to. User code
might be willing to accept lies and in fact, might want them. I think
the real answer is that there is an oddly shaped boundary between lies
being preferable or truth being preferable and that each piece of code
may have a different idea of how to distinguish that line.


Exaclty. A dumper like DDS never wants to be lied to, and hence
avoides using $obj->can, $obj->isa, ref() or anything that allows the
object to lie about itself. Whereas most code should probably let
objects lie to it. There is no black or white about this.

Yves

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


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Joshua ben Jore

On 2/26/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:

On Sun, Feb 25, 2007 at 23:22:13 -0800, Joshua ben Jore wrote:

> Ick Neither ref nor blessed have never been a booleans before and
> even this doesn't change that. Ref couldn't even used to decide if you
> had an object because the two false values '' and '0' can both be
> returned by objects:
>
>  ok( ref( bless( ..., "\0" ) ), 'Detected object' ) # fails
>  ok( ref( bless( ..., 0 ) ), 'Detected object' ) # fails
>
> The only boolean you'll ever have on Perl 5 is defined( blessed( ... )
> ). It's a bad pattern to rely on ref(). Or... all '' and '0' using
> classes were using UNIVERSAL::ref then... maybe... ref() could be
> considered a boolean. I'd have to be convinced.

But do you have an alternative? ;-)


I'm of the opinion that it is clear and blatantly an error to ever use
ref as a boolean. I suppose it depends on who interested I am in being
sure what I've been given is an object or not or perhaps a more
specific question.

The correct boolean is defined( blessed( obj ) ) because this returns
a true value for all objects regardless of goofy class name and a
false value for everything not an object. This is purely because
blessed() avoided ref()'s problem and used undef as its false value
and not ''. It is impossible to bless into undef and this makes
blessed() a better test.


Although...

I also think there may be a difference between code that wants the
"common" truth and other code that wants the "real" truth. Dumping and
serialization code probably wants to avoid being lied to. User code
might be willing to accept lies and in fact, might want them. I think
the real answer is that there is an oddly shaped boundary between lies
being preferable or truth being preferable and that each piece of code
may have a different idea of how to distinguish that line.

Is there any language or notation for making this boundary more
explicit without just salting the code with it? I see things like C as fat or salt or something that has integrated itself into
the code. If it were being talked about separately then perhaps
there'd also be space for dialog about the code's opinions  on proxy
objects, deferred values, isa checking, DOES checking, dunno. All that
stuff.

Josh

PS, it occurs to me that it's odd to accept an object or value. Having
an actual condition like C where you don't also care
about references seems unusual. Are you sure that's not a bug?


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Yuval Kogman
On Sun, Feb 25, 2007 at 23:55:13 -0800, chromatic wrote:

> I wonder if pulling the new DOES() code out of universal.c into a module for 
> 5.9.4 and earlier would alleviate that pain somehow.

I don't know, most of the times I have an if clause trying to figure
out all the possibilities of a value it's because i'm writing a
dispatch table wrapper that will look for a handler based on the
class or something like that.

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgp4GLKtYxek8.pgp
Description: PGP signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Joshua ben Jore

On 2/26/07, Michael G Schwern <[EMAIL PROTECTED]> wrote:

Joshua ben Jore wrote:
> On 2/25/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:
>> Is there a function that is to this as overload::StrVal is to
>> stringification?

Wouldn't that just be CORE::ref $obj ?


No. I don't know how to solve this problem without just wrapping
"CORE::ref" directly. I'm installing a wrapper around
PL_ppaddr[OP_REF] and have a TODO test that says I also wrap
op->ppaddr in all the code compiled before UNIVERSAL::ref is loaded.

The compiled form of CORE::ref() and ref() is identical so I don't
think I can know the difference. It seemed that way on my 5.8.8 and I
didn't look elsewhere.

Since this change is happening at such a low level, there's no way to
prevent the wrapper XS from being involved. At that point, the only
API it responds to is the %UNIVERSAL::ref::hooked hash which is just a
list of superclasses. If the object in ref( OBJ ) is true for
sv_derived_from( hooked_class, obj ) then that obj's scalar(->ref) is
returned instead.

Perhaps anywhere a person has said `no UNIVERSAL::ref' as a user
pragma, that's a place to also defer to the original ref(). I don't do
it now but it doesn't seem like a wrong idea. I opted to go for a
minimal API and add on as necessary.

Perhaps anywhere obj->ref shouldn't be able to call back into obj->ref
and instead go to CORE::ref( obj ) instead. This is dicier.

 # ok, obvious
 sub ref { ref shift }

 # Less obvious what the right thing to do is
 sub ref { foo( shift ) }
 # imported &foo from elsewhere
 sub foo { ref( shift ) }

I'm also pondering whether there's a nice time or place for a nasty
action at  a distance to announce itself to the user. If the user runs
the code under the debugger a warning pops up saying "Woah there!"

So you see, I'm much less certain about this part of the API and thus
I just didn't code it.

Josh


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Yuval Kogman
On Sun, Feb 25, 2007 at 23:22:13 -0800, Joshua ben Jore wrote:

> Ick Neither ref nor blessed have never been a booleans before and
> even this doesn't change that. Ref couldn't even used to decide if you
> had an object because the two false values '' and '0' can both be
> returned by objects:
> 
>  ok( ref( bless( ..., "\0" ) ), 'Detected object' ) # fails
>  ok( ref( bless( ..., 0 ) ), 'Detected object' ) # fails
> 
> The only boolean you'll ever have on Perl 5 is defined( blessed( ... )
> ). It's a bad pattern to rely on ref(). Or... all '' and '0' using
> classes were using UNIVERSAL::ref then... maybe... ref() could be
> considered a boolean. I'd have to be convinced.

But do you have an alternative? ;-)

Realistically, blessing as "0" is intended to make if ( ref $x ) )
return false (at least the one crazy person who did that and
released it on the CPAN intended it to be this way ;-), and blessing
to "\0" probably works similarly.

From perldoc:

   ref Returns a non‐empty string if EXPR is a
   reference, the empty string otherwise. 

I suppose

if ( length( ref $x ) ) { }

is a better test, but when have you ever seen that? I don't think
i'll start using it.

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpsBqvuuswWZ.pgp
Description: PGP signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Christopher H. Laco
Yuval Kogman wrote:
> On Sun, Feb 25, 2007 at 22:34:15 -0800, chromatic wrote:
> 
>> Why not, I already have half of the other stuff in UNIVERSAL
> 
> Just don't tell Adam.
> 

Or me. I have a personal hate relationship with MockObject in this way.
I love MockObject. I hate getting warnings about 3 party modules use of
can in my test suite.

-=Chris



signature.asc
Description: OpenPGP digital signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread demerphq

On 2/26/07, Michael G Schwern <[EMAIL PROTECTED]> wrote:

Joshua ben Jore wrote:
> On 2/25/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:
>> Is there a function that is to this as overload::StrVal is to
>> stringification?

Wouldn't that just be CORE::ref $obj ?



I think Josh is doing something sorta evil with pp dispatch table to
make this work, so im guessing that CORE::ref wont change anything

Yves

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


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-26 Thread Michael G Schwern
Joshua ben Jore wrote:
> On 2/25/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:
>> Is there a function that is to this as overload::StrVal is to
>> stringification?

Wouldn't that just be CORE::ref $obj ?


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread chromatic
On Sunday 25 February 2007 23:04, Yuval Kogman wrote:

> Hmm I usually do
>
> if ( ref $x ) {
> if ( my $class = blessed $x ) {
>
> } else {
>
> }
> }
>
> in code that tries to be very duck friendly.

I wonder if pulling the new DOES() code out of universal.c into a module for 
5.9.4 and earlier would alleviate that pain somehow.

Pure-perl would be easy.  XS is fairly doable.

-- c


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread Joshua ben Jore

On 2/25/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:

On Sun, Feb 25, 2007 at 22:51:43 -0800, Joshua ben Jore wrote:
> On 2/25/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:
> >Is there a function that is to this as overload::StrVal is to
> >stringification?
>
> No. blessed() doesn't lie to you and I don't change that. I didn't
> provide any ref-alike that provide the complete old behavior.

Hmm I usually do

if ( ref $x ) {
if ( my $class = blessed $x ) {

} else {

}
}


Ick Neither ref nor blessed have never been a booleans before and
even this doesn't change that. Ref couldn't even used to decide if you
had an object because the two false values '' and '0' can both be
returned by objects:

 ok( ref( bless( ..., "\0" ) ), 'Detected object' ) # fails
 ok( ref( bless( ..., 0 ) ), 'Detected object' ) # fails

The only boolean you'll ever have on Perl 5 is defined( blessed( ... )
). It's a bad pattern to rely on ref(). Or... all '' and '0' using
classes were using UNIVERSAL::ref then... maybe... ref() could be
considered a boolean. I'd have to be convinced.

Incidentally, check out this madness. Instantly, all objects are invisible.

 package UNIVERSAL;
 use UNIVERSAL::ref;
 sub ref { return }


Wouldn't it be more
thorough to lie to blessed in the same way? People tend to use the
return value from ref and blessed as the class interchangiably once


I think blessed() ought to lie as well but not if the object itself
asks blessed() about itself. I thought it was out of my current scope
to mutate blessed() as well. Right now ref() will lie to anyone but
probably shouldn't lie to an object if it asks this of itself.

I haven't looked hard enough to see how to do scalar( caller() ) in XS yet.

Josh


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread Yuval Kogman
BTW, pure perl blessed() will work:

sub UNIVERSAL::a_sub_not_likely_to_be_here { ref($_[0]) }

sub blessed ($) {
  local($@, $SIG{__DIE__}, $SIG{__WARN__});
  length(ref($_[0]))
? eval { $_[0]->a_sub_not_likely_to_be_here }
: undef
}



I predict that the next anti duck perl idiom is going to be:

eval { $x->UNIVERSAL::can("can") }

to determine "true blessedness" 

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpcwAl4BpfTp.pgp
Description: PGP signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread Yuval Kogman
On Sun, Feb 25, 2007 at 22:34:15 -0800, chromatic wrote:

> Why not, I already have half of the other stuff in UNIVERSAL

Just don't tell Adam.

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpBQt76ylqNT.pgp
Description: PGP signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread Yuval Kogman
On Sun, Feb 25, 2007 at 22:51:43 -0800, Joshua ben Jore wrote:
> On 2/25/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:
> >Is there a function that is to this as overload::StrVal is to
> >stringification?
> 
> No. blessed() doesn't lie to you and I don't change that. I didn't
> provide any ref-alike that provide the complete old behavior.

Hmm I usually do

if ( ref $x ) {
if ( my $class = blessed $x ) {

} else {

}
}

in code that tries to be very duck friendly. Wouldn't it be more
thorough to lie to blessed in the same way? People tend to use the
return value from ref and blessed as the class interchangiably once
they're sure the thing is an object, and they probably use both to
find out if it is an object. This could lead to some very puzzling
bugs (especially if UNIVERSAL::ref is being used by some 3rd party
code, the worst kind of action at a distance).

> If you read t/basic.t file, you'll see a few things marked as TODO. It
> isn't omniscient yet. Its a 0.01 release and probably deserves that.

Does this imply blessed() will lie in the future too?

> Data::Lazy uses this how? Curiously, I would bet this would let
> ref( $obj ) return undef which normally ref() never does. There's also
> the names with \0 in them somewhere. Normally you can't ever bless
> into something with a \0 in it (its just a C string). You could...
> have objects that tell that they're something with a \0 in it. You
> could even return another object. Heh.

Oops, wrong lazy module...
http://search.cpan.org/~audreyt/Scalar-Defer-0.07/

Scalar::Defer blesses into '0' to pretend that the value is not a
ref in the case of:

if ( ref $scalar ) {

}

even though $scalar is an object with all overloads in effect.

It's basically trying to be the mother of all proxies.

I suppose if the value at the end of the thunk turns out to be an
object it probably reblesses itself, or it could even use Data::Swap
to really become that referant (?)... this is purely conjectural
though since I am actually sleeping.

> I think I'm going to be telling Devel::Spy to go use this now too.
> That aims to be a transparent proxy.

Si, same theme ;-)

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpaepv3O23As.pgp
Description: PGP signature


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread Joshua ben Jore

On 2/25/07, Yuval Kogman <[EMAIL PROTECTED]> wrote:

Is there a function that is to this as overload::StrVal is to
stringification?


No. blessed() doesn't lie to you and I don't change that. I didn't
provide any ref-alike that provide the complete old behavior.

If you read t/basic.t file, you'll see a few things marked as TODO. It
isn't omniscient yet. Its a 0.01 release and probably deserves that.


The feature is übersweet, and Data::Lazy should make good use of it
too. You++!


Data::Lazy uses this how? Curiously, I would bet this would let
ref( $obj ) return undef which normally ref() never does. There's also
the names with \0 in them somewhere. Normally you can't ever bless
into something with a \0 in it (its just a C string). You could...
have objects that tell that they're something with a \0 in it. You
could even return another object. Heh.

I think I'm going to be telling Devel::Spy to go use this now too.
That aims to be a transparent proxy.

Josh


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread chromatic
On Sunday 25 February 2007 22:26, Joshua ben Jore wrote:

> I was going to send this just to chromatic because its his
> Test::MockObject but then figured it'd be better to tell perl-qa about
> it.

Why not, I already have half of the other stuff in UNIVERSAL

Looks like a great idea to me.  Shall I assume that it doesn't (by default at 
least) warn that using ref() might not work?  I can justify that warning for 
isa() and can(), but not ref().

-- c


Re: UNIVERSAL::ref might make ref( $mocked_obj ) sane

2007-02-25 Thread Yuval Kogman
Is there a function that is to this as overload::StrVal is to
stringification?

I don't see it on the CPAN yet so I figured I'd ask.

The feature is übersweet, and Data::Lazy should make good use of it
too. You++!

Cheers,

-- 
  Yuval Kogman <[EMAIL PROTECTED]>
http://nothingmuch.woobling.org  0xEBD27418



pgpJuO7JjMzkN.pgp
Description: PGP signature