Beefy Boxes and Bandwidth Generously Provided by pair Networks Bob
XP is just a number
 
PerlMonks  

Re: Use method/function signatures with Perl

by Juerd (Abbot)
on Dec 06, 2004 at 12:03 UTC ( #412628=note: print w/ replies, xml ) Need Help??


in reply to Use method/function signatures with Perl

sub name { my $self = shift; if (1 == @_ && ! ref $_[0]) { $self->{name} = shift; return $self; } elsif (! @_) { return $self->{name}; } else { croak "Unknown arguments to name()"; } }

There is a lot of readability to be gained by just writing it differently:

sub name { my $self = shift; $self->{name} = shift, return $self if @_ == 1 croak "Unknown arguments to name" if @_; return $self->{name}; }
Of course, because I hate methods that return $self (and methods that return something different based on the number of arguments), I would just have this instead:
sub name { my $self = shift; $self->{name} = shift if @_ == 1 croak "Unknown arguments to name" if @_; return $self->{name}; }
which again is easier to read and type. But this is still based on your example. For those who don't mind having the return value being consistent regardless of the number of arguments, there is an even better way to write the accessor, but then the similarity with your example is gone:
sub name { @_ > 1 and croak "Too many arguments for name"; my $self = shift; return @_ ? $self->{name} = shift : $self->{name}; }
(Note that I changed the error message to something that looks like what perl itself uses in such a situation.)

But nothing beats:

sub name : lvalue { shift->{name} }
in writing, reading and maintaining the method, but also in writing, reading and maintaining the code that uses it.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }


Comment on Re: Use method/function signatures with Perl
Select or Download Code
Re^2: Use method/function signatures with Perl
by Ovid (Cardinal) on Dec 06, 2004 at 16:15 UTC

    Juerd wrote: There is a lot of readability to be gained by just writing it differently:

    sub name { my $self = shift; $self->{name} = shift, return $self if @_ == 1 croak "Unknown arguments to name" if @_; return $self->{name}; }

    Minor point: readability is often subjective. I'm not sure if your code is easier to read, but it is more concise. However, it's still not as easy to read (IMHO) is MMD:

    Major point: Perl has an entire class of bugs not found in other languages and in our debating the merits of how to deal with it, both of us have fallen victim to this bug.

    Your code has a bug. Specifically, mine does not allow a reference to be assigned to name. Your code does. This seems like a minor nit but this goes to the code of the problem I am trying to solve. Consider the following snippet from the POD of my module:

    sub name { my $self = shift; $self->set_name(@_) if @_; # I forgot the return! return $self->{name}; } sub set_name { my $self = shift; $self->{name} = shift; return $self; }

    I didn't intend to put a buggy example in my POD, but my bug and your bug are in the same class of bug. Specifically, forcing programmers to check the number and type of arguments is to shift programming burden to the programmer when it can easily be handled by the computer. I gave a live testing demo at Portland Perl Mongers and many who actually did testing admitted they skip this validation in their actual code unless the code is a critical part of the system. Why should this be done? Most languages provide this validation with signatures (though this still only validates type and not domain.)

    Cheers,
    Ovid

    New address of my CGI Course.

      Your code has a bug. Specifically, mine does not allow a reference to be assigned to name. Your code does.

      A major point indeed. I'll abuse it for my own purpose, though: it's the unreadability that made me overlook it! :)

      But the fix is simple and doesn't hurt readability much. You are right that accessor methods are error prone in multiple ways. Fortunately, simple lvalue accessor methods don't have this problem.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (10)
As of 2014-04-19 06:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (478 votes), past polls