Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re: Prototypes allow overloading subs?

by rinceWind (Monsignor)
on Dec 04, 2002 at 10:45 UTC ( [id://217451]=note: print w/replies, xml ) Need Help??


in reply to Prototypes allow overloading subs?

In short, anyone else feel that the java/c way of 'overloading' subs based on the number of parameters is much cleaner then the perl way, and wish that you could use prototypes to do the same thing?
I certainly don't. It would be helpful if you could give an example of an application or a pattern where such a technique of distinct routines to handle different arglists would be useful.

Usually, a routine or method will do a particular job, and the bulk of the code will be independent of the form of parameter passing used. The rest of the code is a wrapper to handle the different types of parameters. This is polymorphism in action - what you are suggesting is violating one of the principles and advantages of OO. In Perl, rather than true polymorphism, most people adopt DWIM when designing the interface.

When it comes to perl's prototypes, I avoid using them, as they are nearly always more trouble than they are worth. I prefer the freeform arglist array that perl gives you in @_, and if I need something complicated, I cast (copy) it to a hash to implement named params.

Also, what I've just said applies to Perl 5. Perl 6 promises to provide much better ways of handling argument lists than Perl 5's prototypes.

Replies are listed 'Best First'.
Re: Re: Prototypes allow overloading subs?
by Ovid (Cardinal) on Dec 04, 2002 at 20:52 UTC

    rinceWind wrote:

    It would be helpful if you could give an example of an application or a pattern where such a technique of distinct routines to handle different arglists would be useful.

    Curiosly, I'm working with a similar issue, so here's an example. Let's say I want to create a 'people' object and save it in the database.

    my $person = People ->new ->first_name( 'Tommy' ) ->last_name( 'Atkins' ) ->email( 'dev@null.com' ) ->save; my $id = $person->get_id;

    The above works if all mutators return the object (typically $self) instead of true.

    Now let's say that later on I want resurrect poor Tommy Atkins from his database internment. Assuming I have his $id, I can do this:

    my $person = People->new( $id ); print $person->first_name, ' ', $person->last_name;

    In the first case we call the constructor with no argument and set all of the data by hand. In the second case we call the constructor with an ID and get what we need. This is method overloading (though I realize we're talking about function overloading, I think the point is the same). In many OO languages, you would code entirely different methods. Let's consider Java (I'm leaving a lot of stuff out here):

    class People { // Java constructors have the same name as the class // People person = new People(); // People person = new People(id); public People() { // initialize empty object } public People( int id ) { // we can now access an object by id } }

    The line public People( int id ) is called the method signature. By allowing the code to dispatch to different methods based upon different signatures, you simplify the logic tremendously. For Perl, without using an external module to fake it, you wind up with something like this:

    sub new { my ($class,$id) = @_; my %data; %data = $class->_initialize($id) if $id; bless \%data, $class; }

    That isn't too complicated, but many people will stick all of the logic in one method or try to do method dispatch based on the number and type of arguments. Further, the more argument types you have to deal with, the more complex this becomes. By forcing the programmer to use extra logic, you increase the chance for bugs. Method overloading on signatures reduces the amount of logic necessary and therefore reduces the amount of bugs and makes the code simpler.

    As a side note, I generally prefere explicit 'get' and 'set' methods rather than overloading those methods. It makes the code easier to understand and doesn't confuse the programmer when they try to do something they shouldn't be able to do.

    # no! If this is mapping to a database, you probably don't # want them to be able to change the id $person->id( $id );

    With the above, it may silently fail. Instead, when the programmer tries to call set_id, they'll likely get a useful error message letting them know that this method is not available.

    Cheers,
    Ovid

    New address of my CGI Course.
    Silence is Evil (feel free to copy and distribute widely - note copyright text)

      In my opinion the perceived "need" for this feature comes from too much attachment to the perfectly ordinary method name "new". Once you realize that not all factory/constructor methods have to be called "new", things become much clearer.
      my $person = People->new()->etc... ... my $himagain = People->restore($id);
      Other useful constructor names can be "new_from_file", "new_named", etc. That way, particularly when the arguments are called $a, $b, $c, you'll have documented what the (sometimes quite substantial) differences are between all the overloaded "new" methods.
Re: Re: Prototypes allow overloading subs?
by Elian (Parson) on Dec 04, 2002 at 21:54 UTC
    It would be helpful if you could give an example of an application or a pattern where such a technique of distinct routines to handle different arglists would be useful.
    Here's an easy one off the top of my head:operator overloading. Not often done, but useful. You would, for example, want to handle multiplication differently if the left and right sides of the * were both matrices then you would if the left side was a matrix and the right a scalar. (In the first example you'd probably do a full matrix multiply, and in the second you'd probably multiply each element of the matrix by the scalar. Probably...)

    Any time you have a sub that checks the passed parameters and then dispatches to different code depending on the type or quantity of the parameters you're a good candidate for this. It's much less error prone (and usually faster) if the language handles the dispatch.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-04-18 12:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found