Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re^3: Runtime introspection: What good is it?

by moritz (Cardinal)
on Jul 07, 2008 at 15:21 UTC ( [id://696011]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Runtime introspection: What good is it?
in thread Runtime introspection: What good is it?

That way you add "alien" methods to your data structures, which are the wrappers I wrote about.

The problem with wrappers is that they aren't very re-usable. In the example above you assumed that the sub what_does_it_return is in your own code base, or easily overridable. That's not necessarily the case. So you have to hope that whoever wrote the module you're using has built proper, reusable and maintainable wrappers.

In contrast when you have introspection built into your language's OO model, you can just use that, and it will work fine.

Another problem with overloading is that it doesn't scale very well. If you have a million data objects, why should you overload them all if you just want to call a method on one of them?

Both of my points have in common that you need to plan in advance. You need to know or guess how the result objects of, for example, a de-serializer will be used. But you can't, because in the general case the one who uses your module is cleverer that you and, and more creative, and most of all he's crazier. He'll get some weird ideas of what to do, and there won't be wrappers in place, so he'll have to resort to something different.

So runtime introspection is at once lazy and humble - lazy because you don't try to guess in advance all use cases, and humble because you don't think you can guess them all.

That's the reason why Perl 6 has a pluggable object model that allows introspection - if something is missing or gone wrong, it's relatively easy to add, fix or replace afterwards.

Replies are listed 'Best First'.
Re^4: Runtime introspection: What good is it?
by stvn (Monsignor) on Jul 07, 2008 at 21:11 UTC
    That's the reason why Perl 6 has a pluggable object model that allows introspection - if something is missing or gone wrong, it's relatively easy to add, fix or replace afterwards.

    s/Perl 6/Perl/

    Perl 5 may not be as sexy as Perl 6, but it has just as flexible an object model, otherwise I would have never been able to write Moose or prototype the p6 model in it, not to mention all the Class:: stuff on CPAN that others have written.

    -stvn
      Perl 5 may not be as sexy as Perl 6, but it has just as flexible an object model...

      I'm less convinced. The facts that SUPER:: is broken in Perl 5 (it doesn't respect dynamic scoping) and that you can't tell a method from a subroutine make Perl 5 OO slightly more difficult to manage.

        SUPER:: is broken in Perl

        Check out SUPER, it might help you there ;)

        you can't tell a method from a subroutine

        Yeah I agree that is annoying too, however it is possible to get some stuff. For instance, in Moose we differentiate between exported subs from another package and subs defined in that package. Then there is also stuff like MooseX::Method which make it easier to "tag" methods and therefore tell them apart.

        But yeah in the end I will agree there are some broken parts to Perl 5 OO model, but the fact that I can fix most of them and provide a decent hack to work around or at least minimize the others is a pretty good. Try that in Java/C#/etc.

        -stvn

        For your own code you can use attributes (experimental feature) to signal what's a method and what's not.

        sub foo :method { my $self = shift; # ... return; } sub bar { # ... return; } use attributes; sub is_a_method { scalar grep $_ eq 'method', attributes::get($_[0]); } for ([ foo => \&foo ], [ bar => \&bar ]) { print "$_->[0] is a " . (is_a_method($_->[1]) ? 'method' : 'function +') . "\n"; } __END__ foo is a method bar is a function

        lodin

Re^4: Runtime introspection: What good is it?
by BrowserUk (Patriarch) on Jul 08, 2008 at 01:44 UTC
    which are the wrappers I wrote about.... So you have to hope that whoever wrote the module you're using has built proper, reusable and maintainable wrappers.

    Those "wrappers" are just bog-standard 'subclasses'. And you'll quickly discover whether they are written correctly the first time you try to use a missing method, it'll fail.

    In contrast when you have introspection built into your language's OO model, you can just use that, and it will work fine.

    *&^£"*$^*"^£*$^. Sorry, but that just isn't the case. If you need to call method $o->doSomeThing(), and the objects class doesn't support that method, UNIVERSAL::can() will tell you that you can't call it, but it won't give you an alternative so what you gonna do?

    You have three choices:

    1. die
    2. warn and return undef.
    3. Try $o->doSomethingElse()?

    And you can, more easily and efficiently, do any of those without introspection:

    ... eval { $o->doSomething() }; $@ and die ...; # or $@ and warn( ... ) and return; ## or $@ and eval{ $o->doSomethingElse() }; $@ and eval{ $o->doYetSomethingDifferent() }; $@ and eval{ $o->${ ( $o->giveMeAListOfWhatYouCanDo() )[ 0 ] }() }; $@ and die "Apparently $o doesn't know how to do any damn thing!";
    Another problem with overloading is that it doesn't scale very well. If you have a million data objects, why should you overload them all if you just want to call a method on one of them?

    Again, not so. Outside of prototype-based objects (which are possible in Perl as this hoary old piece of code of mine from a million years ago shows), the adding of a method to a class or subclass doesn't affect the scalability of the class instances.

    Slightly untrue for the example of adding a clone() methods to Perl's built-in types, but as I've mentioned elsewhere, they are something of a special case, in as much as they do not act as objects unless you bless them. This is a similar quandary to the Java string vs. String (and to some degree StringBuffer) issue. Native types trade flexibility for performance. Performance may not be on the top of everyones list of priorities--indeed its not mine--but when you need it, you damn well better have it. Especially in the absence of deep, compile-time optimisation. Ie. In dynamic languages.

    If you have a million data objects, why should you overload them all if you just want to call a method on one of them?

    I can't wrap my head around this. It seems like the classic justifiction (non-argument) to me.

    If you have a million instances of some class:

    • Why would want to only perform some operation on one of them?
    • How do you know (guess?) that you'll only need to do it to one instance when designing your class?
    • Which instance will it be?
    • And how will you recognise (guess?) that instance at runtime?
    • If this instance is different from all the other instances, why is it an instance of this class in the first place?

    I could go on (and on, and on) about the principle and tenants of OO ... but I'll stop here :)

    Both of my points have in common that you need to plan in advance. You need to know or guess how the result objects of, for example, a de-serializer will be used. But you can't, because in the general case the one who uses your module is cleverer that you and, and more creative, and most of all he's crazier. He'll get some weird ideas of what to do, and there won't be wrappers in place, so he'll have to resort to something different.

    Again, not so. When you write (design) your class, you incorporate just those methods required for your application of that class. If you user wants more or different, he subclasses your class. Or uses a mix-in. Or composes his own class that has-a instance of your class. Or overrides your methods with his own. Or...

    Prior to the current moves to add RTTI to C++, there was no possibility of runtime introspection, and yet no one had problems doing found it impossible to do any of these things.

    It may be that there are some use cases for which introspection in easier or more efficient to code and debug. Or easier to comprehend. And it is these cases that I'm interested in hearing about. But so far, I haven't.

    So runtime introspection is at once lazy and humble - lazy because you don't try to guess in advance all use cases, and humble because you don't think you can guess them all.

    As a strong advocate of YAGNI, I'm very much in tune with the ideal of not trying to guess the future, or what uses a user may find for your code. But you do not need introspection to pursue or achieve that ideal. Indeed, you do not need OO to pursue that ideal! In fact, I would say that in many cases, OO is used when it is unnecessary and tends to breed the whole 'future proofing' spoof. But that's another argument :)

    But if you are going to use OO, I strongly believe that compile-time inheritance and composition have all the bases covered--from an 'it's possible' perspective. The only questions in my mind are:

    • Can run-time introspection simplify or clarify some of those bases?
    • What are the knock on costs in terms of (for example) trying to debug a system that modifies classes--and worse, instances--at runtime?

    This rings huge alarm bells in my head. Taking me back to the bad ol', bad ol' days of COBOL and Fortran compilers that emitted self-modifying code. I only had to try and debug a piece of that code once. Never--I say *NEVER*--again. Pouring over crash dumps trying to first find, and then decompile the code and stack traces to work out what code had been generated at run-time, that crashed. And that's before you could even begin to think about the un-captured, data-driven code path that lead to it being generated, or why what was generated, crashed.

    Never again!.

    That's the reason why Perl 6 has a pluggable object model that allows introspection - if something is missing or gone wrong, it's relatively easy to add, fix or replace afterwards.

    Maybe, a year or two from now Perl 6 will go live. And maybe, a year or five after that, I'll be looking back at this thread thinking: what was all the fuss about.

    Maybe, I'll reach a similar conclusion to that I have about OO. Used properly, without the 'everything must be' dogma, and not overused, or used for the sake of it, runtime introspection will become just another tool in the toolbox.

    But for right now, I remain decidedly unconvinced. I can see uses. I can see (some) convenience. But I cannot see any 'killer application'. And I'm very skeptical about the debug-ability and maintainability.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://696011]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2024-04-19 21:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found