in reply to Re^3: how to goto &sysread ?
in thread how to goto &sysread ?

Simply put, you do not "goto" a function or a subroutine. You "call" the function or subroutine, which means: save my current place in the code and go do something and when that is done resume my code after this "call". If you "goto" or "jump" directly into some function's or subroutine's code, it will cause a crash because the preamble of "where to go back to when I am finished" was not done.

I'm not sure, but it could be that you don't know what goto(&func); does. goto(&func); is basically return &func;, except it tears down the current stack frame first.

>perl -MCarp=confess -e"sub h { confess; } sub g { h(); } sub f { g(); + } f();" at -e line 1 main::h() called at -e line 1 main::g() called at -e line 1 main::f() called at -e line 1 >perl -MCarp=confess -e"sub h { confess; } sub g { goto &h; } sub f { +g(); } f();" at -e line 1 main::h() called at -e line 1 main::f() called at -e line 1

It's perfectly safe.

IIRC, goto(&func); is slower than return &func;, but it can save memory in deeply recursive functions. The main purpose is too fool Carp.

Replies are listed 'Best First'.
Re^5: how to goto &sysread ?
by Marshall (Canon) on Jul 25, 2011 at 06:39 UTC
    Yes, you are correct. I was unaware of this.

    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 @_.

    It appears that this is sort of like an exec() at the subroutine level. That it can "fool" caller() is significant.

    In the process of thinking about the OP's question, I have learned something. But I'm still curious as to what the OP is trying to do? The above notwithstanding, what is the application?

Re^5: how to goto &sysread ?
by Tanktalus (Canon) on Jul 26, 2011 at 14:06 UTC

    Apparently, which is slower depends on your version of perl... :-)

    Here's the benchmark code I used. Now, it's not entirely fair because I'm not testing with a long list of parameters - Benchmark is going to only pass in a single parameter. However, it's a start.

    #!/usr/bin/perl sub dest { return 1 } # don't want it optimised away use Benchmark qw(:all); cmpthese(-1, { goto => sub { goto &dest; }, call => sub { return dest(@_); }, callamp => sub { return &dest; }, });
    And the results? They depend on the version of perl. Using just the oldest and newest perls I have:
    $ perl5.8.8 x.pl Rate call callamp goto call 4283398/s -- -9% -29% callamp 4693114/s 10% -- -22% goto 5996757/s 40% 28% -- $ perl5.14.1 x.pl Rate call goto callamp call 4633858/s -- -9% -12% goto 5119310/s 10% -- -2% callamp 5242879/s 13% 2% --
    Of course, nothing of import is actually happening, the code in the called function will likely completely overwhelm the calling, so (and I'm sure you, ikegami, know this) don't base which one you use on the performance - there is no real significant difference - even the slowest one in perl 5.8.8 only takes 2.3e-7 seconds (on my CPU), which amounts to a couple hundred CPU cycles. Any REAL work you're doing will so completely overwhelm this that the so-called "savings" between calling it one way vs another will be nothing more than noise. Use the one that does what you mean, the maintainers (which likely will include yourself 6+ months from now) will thank you.