Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • So how do I figure out those methods short of running the code? I can't.

    Without some kind of static analysis, you are just not going to be able to do that, but even that most likely won't get you what you want.

    Think for a moment about introspecting classes without executing code. If you look at a language like Perl 6, where classes can be created, destroyed and modified at runtime. You need to have a highly dynamic meta-model and a meta-model is a living thing which means you have to execute some code.

    Even with something as vanilla as the Java object model, you still have introspection and reflection capabilities which will defeat any type of static analysis. And IIRC the Java code must be compiled and loaded into the JVM before you can actually introspect it too, which is pretty much equal to "running the code" in JVM land.

    Hell, even if I could, this could easily trip me up:
    [/snip code example]
    I could check to see if the method was defined in the class hierarchy:
    [/snip code example again ...]

    You do realize that Class::MOP will give you these things, in a much cleaner and simpler way?

    package Foo;
    use HTML::Entities 'encode_entities';
    # ...
    package main;
    my @methods = Class::MOP::Class->initialize('Foo')->compute_all_applicable_methods()

    This will return a list of all the methods names that Foo will respond to, taking into account inheritance and properly excluding imported methods. The list will be a list of HASH refs, each one containing the following; method name, the name of the class in which the method lives and a CODE reference for the actual method. And no, you don't need to use Moose to get this, nor do you need to alter your class at all, Class::MOP::Class will read all your package information and leave it just as it was found. No soapy residue :)

    Perl is too random and has no real introspective capabilities. Perl 6 solves a lot of this, but I'm writing Perl 5.

    I disagree with this completely. To start with Perl 5 has more introspection capabilities then any other language (short of LISP maybe) that I have encountered (and I am a language fetishist, so I have seen lots!). Not only can you walk the entire package namespace tree at runtime, examing and/or altering just about anything you could possibly want to, but you can actually do the same thing with the compiled opcode tree! Now, I will agree with you that the API for that kinda stuff is at best difficult and at worst absolute total crap, but it is there. While Perl 6 will surely provide a better API to this kind of stuff, I actually suspect that we will actually loose some of this introspection capabilities in the end (unless someone write B::PIR or something).

    Moose might help, but having a generic serialization tool and a custom deserialization tool? That's no good (though I wouldn't mind custom tools to be built on a generic system).

    I think you are missing the point of what Moose could offer you here. Moose brings consistency to Perl 5 OO, it cuts through the jungle of TIMTWODI-gone-bad while still allowing you a whole lot of freedom to wander off path. If you want to build a round-tripping serialization/deserialization tool, you MUST have some degree of consistency in the representation of your classes and objects. This is why MooseX::Storage 0.01 was able to be written over the couse of a 2 hour train ride from New Haven to NYC, it builds on the consistency that Moose provides and the introspection capable throug the MOP.

    Of course, this problem is wider than just Perl. Even being able to deterministically list all methods and know which ones are actually for "fields" (or slots, or properties, or whatever your term of choice is), doesn't tell me much about the intent of those methods.

    Okay, you will probably never find a tool that can divine programmer "intent", from just code. The programmer must supply meta-information to tell both the compiler and any possible humans reading the code, what it might be doing. So, to beat a dead Moose once more ....

    Take the following class:

    package Foo;
    use Moose;
    has 'bar' => (is => 'rw', isa => 'Str');

    Here is one way to find out the "intent" of the 'bar' method in the Foo class above.

    print Foo->meta->get_method('bar');

    This prints "Moose::Meta::Method::Accessor=HASH(0x18f69b4)", which tells me that this is an accessor method generated by Moose. It also isa(Class::MOP::Method::Generated) as well, which tells me that Moose created it. But wait, this is not all, I can also tell what attribute this method is associated with, like so:

    print Foo->meta->get_method('bar')->associated_attribute->name; # prints "bar"

    I can even get a little silly and loop back around to find the same method ref.

    refaddr Foo->meta->get_method('bar') == refaddr  Foo->meta->get_method('bar')->associated_attribute->associated_methods->[0];  # TRUE

    And once you get the attribute meta-object (Foo->meta->get_attribute('bar')) then you can review all the metadata supplied by the programmer (such as the type "Str" and any of the defaults Moose supplies) and get a really good idea of what that method might do as well as how that attribute/slot/property is treated by the class. It's no crystal ball, but it is about as close as you will get in Perl 5 or 6, as I doubt that Perl 6 will end up implementing the entire Moose meta-model.

    In conclusion, ... why the **** are you not using Moose!?!?! It seems like it has pretty much everything you want, and anything that is missing I suspect can be added by extending the MOP. I will even go so far as to offer to buy you dinner and drinks at your favorite pricey Portland restaurant and/or goth-bar during OSCON (assuming we both end up attending) if Moose doesn't already handle or can not be cleanly extended to handle all your needs.

    What do you say? Ready to drink a little Moose-Aid?

    - Stevan

    • While Perl 6 will surely provide a better API to this kind of stuff, I actually suspect that we will actually lose some of this introspection capabilities in the end (unless someone write B::PIR or something).

      I can think of someone who has experience with Parrot, PIR, the Perl 6 object system, and the B:: modules.... I'm waiting for a couple of other pieces of Parrot to be ready before that will work.