develooper Front page | perl.perl5.porters | Postings from March 2007

Re: [PATCH] Extend functionality of UNIVERSAL::DOES() so it handles additional roles, and works in subroutine form.

Thread Previous | Thread Next
From:
demerphq
Date:
March 15, 2007 06:10
Subject:
Re: [PATCH] Extend functionality of UNIVERSAL::DOES() so it handles additional roles, and works in subroutine form.
Message ID:
9b18b3110703150609m10a0893fyb25b50ec9b27dadc@mail.gmail.com
On 3/12/07, chromatic <chromatic@wgz.org> wrote:
> On Monday 12 March 2007 01:29, demerphq wrote:
>
> > > Calling it UNIVERSAL::DOES() -- when DOES() is a method in UNIVERSAL adds
> > > to the mess.
>
> > Saying its a method is just trying to force a world view onto perl 5
> > that doesnt exist.
>
> $ perldoc UNIVERSAL
>
> NAME
>        UNIVERSAL - base class for ALL classes (blessed references)
>
> ...
>
>         UNIVERSAL provides the following methods:
>
> What form of object orientation stores functions--not methods--in the
> universal base class?

The same kind of object orientation that we have in Perl. And the same
kind of OO that makes UNIVERSAL::isa() useful as function.

It might not have been the best design plan in the world, but it does
make a certain set of sense, but only if you dont force yourself to
imagine that OO /must/ work like it works in certain other OOriented
languages.

Its too late now to pretend that there isnt an equivelence between
subs and methods.

> > I think if that view pervails than UNIVERSAL::DOES in its current form
> > should be removed from blead. It doesnt really advance things,
>
> I think you don't understand how it works.

Considering ive examined the code with a microscope, and patched it to
be much more useful, thats a pretty bold claim.

> > isnt useful by itself,
>
> Untrue.

Yes true. How do you know that you have an object? Because it didnt
die when it was used?  Thats not very useful for introspection code.

Whats the use case of a routine like this? I imagine it would be much
the same as UNIVERSAL::ISA() is used for, that is dispatch based on
ability to fulfil a role. And in that case non objects are just as
likely to need introspection as objects are.

This is a point you seem not to want to address. I really wish you would.

> > isnt documented that it needs helper subs from a
> > different module
>
> That's true only because it doesn't *need* helper subs from a different
> module.

Actually it does. Or you have to make a big, potentially fatal error,
kind of assumption that you are being passed an object. And if you are
going to make that assumption WHY ARE YOU BOTHERING TO INTROSPECT AT
ALL? Just use the item as tho it fulfils whatever role you want, and
if it doesnt fulfil it, well, Perl will ALSO throw an error.

> You seem to have the impression that DOES() is broken because you can't use it
> on non-invocants.

No i think its less than useful because of it. I dont consider it
broken, i consider it so far less than useful that it doesnt belong in
core in its current form.

> Of *course* you can't use it on non-invocants.  It's a method!  I wrote it for
> objects!  That's its purpose!

Thats nice, but since you need to have a way to check that what you
call it on is not an unblessed reference It doesnt seem very useful.
Between Scalar::Util::blessed() and UNIVERSAL::isa() we already have
this functionality in core. Why should we have DOES as well?

> You can't call new() or DESTROY() on non-invocants either; are they broken?
> Do they need function forms?  Should there be a UNIVERSAL::DESTROY() that you
> can scatter willy-nilly through your code?

You dont call DESTROY on a class method. And normally you dont call
new on anything but a classname. So its not a good contrast IMO.

> (Acme::UNIVERSAL::new already exists.  I highly recommend it for everyone on
> this list who still has the inkling that calling methods as functions is
> remotely sane.)
>
> > What does it do that isa() doesnt do?
>
> It's overridable by subclasses for things such as Test::MockObject,
> Test::MockObject::Extends, proxy objects, and roles such as in Class::Trait
> to override and to query without causing people to flipping the bozo bit that
> trips when they even consider the possibility that the thought of overriding
> isa() might cross someone's mind.

So its a workaround for the fact that UNIVERSAL::isa() doesnt
necessarily return the same thing as $obj->isa(). Which says to me
that it should fix the problem with UNIVERSAL::isa() and not just
provide a way to do an isa lookup that MUST happen via a method call.

> You know--normal object stuff that people do when they don't get wrapped up in
> the tiny little world of structural typing and polymorphism based solely on
> inheritance.
>
> Why does it fall back on isa()?  First, because inheritance also provides an
> allomorphic relationship.  It's certainly not the only way, but it is one
> way.  Second, because copy and paste is a terrible mechanism of code re-use,
> and isa() is already working, tested, and debugged code.
>
> Why does it not do anything besides isa() by default?  Because, by default,
> the only way to mark an allomorphic relationship in Perl 5 is to note it
> yourself.  UNIVERSAL can't detect that.  No code can.  That's why roles are
> important beyond duck-typing with can().  Sure, maybe you can tell the
> difference between Tree::bark() and Dog::bark(), but good luck solving that
> class of problems in general algorithmically.
>
> Again, I have absolutely *no* objection to adding a new does() or DOES()
> operator or does() function to Scalar::Util or wherever, or whatever name
> makes the most sense--but UNIVERSAL::DOES() is not and should never be a
> function.  It's a method!  That's why it's in UNIVERSAL, so that the DOES()
> method is available to all classes and does something allomorphically
> sensible for all invocants!

The problem with this is conceptual. This new keyword has to hook into
some kind of method in order to facilitate overriding. Which to me
makes even less sense  than making UNIVERSAL::DOES() behave as my
patch does.

And the reason I think UNIVERSAL::DOES() is the right place for this
behaviour is exactly the reason you outline above, BUT that I consider
the utility and practicality of being able to use this function/method
on things that I dont *know* are objects in the first place to
outweigh the concerns that you have raised, which frankly to me are
more or less aesthetic given the state of Perl 5 OO. .

> If you want UNIVERSAL::DOES() to work on things that aren't valid invocants,
> make them valid invocants instead and solve a host of other problems!

Sorry, but this view is a non starter. autoboxing is a _very_ big
kettle of fish, and its not an appropriate way to resolve these
problems. Sure it would be nice, but its not a viable solution, and is
very much unlikely to happen any time soon. Certainly not in a way
that doesnt require more intrusive changes than that required to use
the UNIVERSAL::DOES that i would like to see.

Cheers
Yves




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

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About