Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

method aliases with goto(&NAME)

by citromatik (Curate)
on Sep 17, 2013 at 10:52 UTC ( [id://1054418]=perlquestion: print w/replies, xml ) Need Help??

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

For legacy reasons I want to include a couple of method aliases in a production API. One simple way of doing this is something on the lines of:

sub legacy_method { my ($self, @args) = @_; return $self->current_method(@_); }

But I am wondering if an alternative using goto would serve for this purpose:

sub legacy_method { goto(&current_method); }

Due to the characteristics of this version of goto it looks like a sensible approach. So far it passes the tests and seems to work fine, but I would like to ask if anyone sees any drawback to this approach.

citromatik

Replies are listed 'Best First'.
Re: method aliases with goto(&NAME)
by tobyink (Canon) on Sep 17, 2013 at 11:32 UTC

    Won't somebody please think of the children?!?!.

    package Parent { sub legacy_method { my ($self, @args) = @_; return $self->current_method(@args); } sub current_method { return 1; } } package Child { use base 'Parent'; sub current_method { return 2; } } Child->legacy_method; # returns 2

    If you swap in your goto implementation of the legacy method, then calling Child->legacy_method returns 1.

    Here's an alternative safer version using goto...

    sub legacy_method { my $next = $_[0]->can('current_method'); goto $next; }

    See also http://tvtropes.org/pmwiki/pmwiki.php/Main/ThinkOfTheChildren.

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
      > If you swap in your goto implementation of the legacy method, then calling Child->legacy_method returns 1.

      Don't you think this could perfectly be the intended behavior, since Child doesn't seem to have any legacy_method?

      But your right that the OP was wrong about the equivalence.

      Cheers Rolf

      ( addicted to the Perl Programming Language)

        There are probably instances where you'd want two methods that behave identically in the parent class, but behave differently in the child class. However, given that the title of this thread mentioned "method aliases", I'm assuming the intention is that legacy_method acts as an alias (i.e. behaves identically) for current_method, unless a child class explicitly overrides legacy_method to make it behave differently.

        use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

        Don't you think this could perfectly be the intended behavior, since Child doesn't seem to have any legacy_method?

        Not for one second. The child provides a correct interface. The legacy caller uses a correct interface. It should work.

Re: method aliases with goto(&NAME)
by Anonymous Monk on Sep 17, 2013 at 10:57 UTC

    ask if anyone sees any drawback to this approach.

    There are none except in the name -- goto -- kinda like "eval" -- scary for the scaredy

    OTOH *oldname = *newname;

      OTOH *oldname = *newname;

      Yes, I also thought about something like that, but the goto version allows to include more code in the legacy method if needed:

      sub legacy_code { warn ("This method is deprecated, use current_method instead"); goto(&current_method); }

      citromatik

Re: method aliases with goto(&NAME)
by ikegami (Patriarch) on Sep 18, 2013 at 19:24 UTC

    What are your motivations?

    Modify the stack to pretend `legacy_method` wasn't called is surely detrimental. You could avoid that (and speed things up an itsy bit) with the following:

    sub legacy_method { &current_method; }

    But both the above and your approach fail when a child class overrides current_method. I'd use the following:

    sub legacy_method { my $self = shift; $self->current_method(@_); }

    (Which actually works and avoids needless copying unlike the code you presented as the baseline.)

Re: method aliases with goto(&NAME)
by manorhce (Beadle) on Sep 17, 2013 at 11:07 UTC

    Please follow the below link which is already in Perl monk http://www.perlmonks.org/?node_id=7947

Re: method aliases with goto(&NAME)
by zork42 (Monk) on Sep 18, 2013 at 08:50 UTC
    Are you using Moose?
Re: method aliases with goto(&NAME)
by sundialsvc4 (Abbot) on Sep 17, 2013 at 12:41 UTC

    “Scary” is the ultimate under-statement.   “Unmaintainable” is its second cousin.

    You probably have a short-list of possibilities where this code can actually “go to.”   Put this into the code such that it cannot go anywhere else without dieing.   For example, return a string or a constant, then use a if {goto} elsif {goto} else {die} construct.   It still sucks but it sucks slightly less.   Now, you do not have to “look somewhere far-away to see what it is supposed to be doing, then cross-your-fingers to see if it actually does it.”   That’s exactly the sort of thing that causes pagers to go-off at 3AM.

      You might be misunderstanding what...

      goto(&current_method);

      ... does. It doesn't execute &current_method, and then go to whatever label was returned from &current_method. It just goes to &current_method. It's not scary; it's not unmaintainable; it's just a tail call.

      From perlfunc (my emphasis):

      The goto-&NAME form is quite different from the other forms of goto. In fact, it isn't a goto in the normal sense at all, and doesn't have the stigma associated with other gotos. Instead, it exits the current subroutine (losing any changes set by local()) and immediately calls in its place the named subroutine using the current value of @_. This is used by AUTOLOAD subroutines that wish to load another subroutine and then pretend that the other subroutine had been called in the first place (except that any modifications to @_ in the current subroutine are propagated to the other subroutine.) After the goto, not even caller will be able to tell that this routine was called first.

      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

      “Scary” is the ultimate under-statement. “Unmaintainable” is its second cousin. ...

      Cryptic advice -- no friend to clarity and understanding

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1054418]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (3)
As of 2024-03-19 03:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found