http://qs321.pair.com?node_id=656943

zrajm has asked for the wisdom of the Perl Monks concerning the following question:

I just started writing things using the object oriented perl interface, however I sincerely miss prototypes! Is there a way to add prototypes to my object methods, so that I get an appropriate warning if someone use the method with wrong number or types of arguments?

perlobj refers to "Function Templates" in perlref, which speaks a bit about creating local subroutines. Is there something along this way that one would want to use, in order to get object method prototypes?

/zrajm

P.S. I got quite suprised when I realised that my prototypes where being ignored when calling a method. How come this is so?

Replies are listed 'Best First'.
Re: Object method prototypes?
by perrin (Chancellor) on Dec 14, 2007 at 00:28 UTC
    To do this sort of argument checking in Perl, you use a module like Params-Validate.
Re: Object method prototypes?
by Joost (Canon) on Dec 14, 2007 at 00:36 UTC
    Prototypes are determined at compile time and with that come several restrictions that make it a very bad fit for object-oriented constructs in perl. For one, it's terribly hard in specific cases and in general impossible for the perl compiler to determine an object's class at compile-time (i.e. by static analysis of the source code) so it won't be able to check which of any number of same-named functions will be used in a method invocation.

    Also, perl's prototypes are really not about argument checking. They are about argument coercion - they don't really match what prototypes in C or Java for instance do.

    See also Far More Than Everything You've Ever Wanted to Know about Prototypes in Perl

      Yup. shmem referred me to that document in the chatterbox. So the first thing I did after starting this thread was to read it.

      And I don't think I'll be using prototypes much any more..

Re: Object method prototypes?
by moritz (Cardinal) on Dec 14, 2007 at 00:07 UTC
    Prototypes on methods are ignored because prototypes essentially change the way perl parses the code.

    And since the type of a reference is not known at compile time, the parser has no way to find out if there is a prototype to a method, and if yes, which.

Re: Object method prototypes?
by dragonchild (Archbishop) on Dec 14, 2007 at 00:48 UTC
    You don't miss prototypes. You only think you do. You might want to consider changing how you look at subroutine parameters and switch everything to be a hashref. This allows you to do a number of things:
    • Future-proof your code by easily adding new parameters without modifying every caller
    • Allow for optional parameters
    • Make your parameters positionless
    • Allow you to be able to have different classes handle a given invocation easily.
    • Allow you to validate it more easily.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      I like named parameters, but I don't like hashrefs. (update: for parameter passing, I mean)

      When I need more than 2 or so parameters I tend to use this construct:

      sub my_method { my ($self,%args) = @_; # now do stuff with $self and %args } # which is called as $object->my_method( foo => $value, bar => $bee );
      Saves typing and IMHO is nicer to look at at both sides.
        That works, as long as you don't mind creating and destroying an argument hash every time your method is called. Passing a hashref would avoid that, but unless you're writing performance-sensitive code it doesn't matter much.
Re: Object method prototypes?
by shmem (Chancellor) on Dec 14, 2007 at 01:05 UTC

    First argument to a method is its object, whose type is not known at compile time, so the first prototype of a method has to be ignored anyways.

    Does it make sense to test for the rest of them? I'm glad it was so decided that it doesn't, given the perl5 method call implementation.

    Things would be different if a method's object wouldn't appear at all in its arguments, but be magically shoehorned into the method's function body as, say, $self, which would mean having a special variable different from all other special variables (of which perlvar tells) in that it is strictly localized and reserved - if and only if the function in question is called as a method.

    The current implementation is easier to implement (since it's done ;-) Have to see what Perl 6 says...

    But anyways - you don't need prototypes, except maybe for the & (subroutine/block) type of prototype.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      I'm absolutely amazed at the speed with which you all replied and the usefulness of your answers. Why, oh why, did I not become a PerlMonk earlier?

      It seems my ideas about what prototypes was all about needed some serious corrections. Many thanks to all of you above for helping me become a better perl programmer. :)

Re: Object method prototypes?
by petdance (Parson) on Dec 14, 2007 at 02:58 UTC