Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

goto &sub and local question

by rovf (Priest)
on Nov 24, 2008 at 09:00 UTC ( #725531=perlquestion: print w/ replies, xml ) Need Help??
rovf has asked for the wisdom of the Perl Monks concerning the following question:

I have a (somewhat esoteric) question about the usage of local in the context of the special form goto &SUB. Here is my example code:

use strict; use warnings; use Data::Dumper; sub s1 { print "Second: ",Dumper(@SomePackage::_data),"\n"; } sub s0 { local @SomePackage::_data=(45,'D'); print "First: ",Dumper(@SomePackage::_data),"\n"; goto &s1; } s0
Running this program produces the following output:
First: $VAR1 = 45; $VAR2 = 'D'; Second:
I do not understand why @SomePackage::_data is empty within s1.

My understanding of local is that it creates a new copy of _data, which shadows the previous one until the end of the current sub. This new copy of _data is visible in this subroutine and all subs called from this one (unless, of course, shadowed by a new local declaration.

My understanding of goto &s1 is that control is transfered to the subroutine s1 without any change in the stack.

Therefore, since _data is non-empty within s0, it should be non-empty within s1. Where do I make a mistake here?

-- 
Ronald Fischer <ynnor@mm.st>

Comment on goto &sub and local question
Select or Download Code
Re: goto &sub and local question
by ikegami (Pope) on Nov 24, 2008 at 09:08 UTC

    My understanding of goto &s1 is that control is transfered to the subroutine s1 without any change in the stack.

    Read the docs!

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

    "No changes to @_" is not "no changes to the stack". Quite the opposite, the goal of goto &name is to remove the current stack frame.

    You want just &name;, not goto &name;. It preserves @_ without removing the current stack frame.

    sub s1 { our $var; print "arg: $_[0]\n"; print "local: $var\n"; } sub s0 { local our $var = 'local'; &s1; } s0('arg');
    arg: arg local: local

    Update: Initially, I accidentally left out the bit about &name;. Added.

      You want just &name;, not goto &name;.

      Thanks a lot for the clarification. Unfortunately, in my particular application I think I need the 'goto' form, but I can solve the problem by using just usual package global variables. It's not a nice solution, but it affects only a few closely coupled subroutines, so I don't think I will run into maintenance problems.

      -- 
      Ronald Fischer <ynnor@mm.st>

        "Unfortunately, in my particular application I think I need the 'goto' form ..."

        Why? What about your usage requires you to call a subroutine with goto? After all, "the author of Perl has never felt the need to use this form of goto."

        Also, you mention that your solution is to affect a few closely coupled subroutines with global variables. I can't help but associate the word closely with the word tightly -- which is exactly how subroutines are not supposed to be coupled. Loose coupling and tight cohesion is the goal. I can't help but think that maintenance problems are all that you are adding and that there is a better solution for you, but it is difficult to know for sure without seeing more of your code.

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: goto &sub and local question
by ccn (Vicar) on Nov 24, 2008 at 09:09 UTC

    perldoc -f goto (the bold is mine)

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

    So localization is lost before s1 call

Re: goto &sub and local question
by Bloodnok (Vicar) on Nov 24, 2008 at 09:14 UTC
    Is it not the case that goto &sub constitutes a call preserving the call stack to the called sub whereas the local definition does not modify the call stack, hence is not seen by the called sub, but instead instantiates a global variable locally ??

    Or am I, once again, missing something fundamentally obvious ??

    Update

    Or as both ccn & ikegami both so eloquently put it when they were quicker to the draw ...

    A user level that continues to overstate my experience :-))

      That's what I thought too, but as it was pointed out above, it is not correct, and if I had read the docs instead of trusting my memory, I wouldn't have posted this question. After all, the docs clearly say that localization is undone.

      Whether this is a nice concept or not, is another question. It seems that when you want to pass control to another sub without creating a new stack frame, the only possibility to pass additional information accross the goto &... boundary is by using global (non-localized) variables.

      OTOH, I think the occasions to use such a construct are so rare that it's not so bad to use a non-localized global variable for this task. </c>

      -- 
      Ronald Fischer <ynnor@mm.st>
        the only possibility to pass additional information accross the goto &... boundary is by using global (non-localized) variables.

        Depending on the use case you might be able to pass the data via @_:

        sub s1 { my $data = pop; print Dumper $data; } sub s0 { push @_, [45, 'D']; goto &s1; } s0;

        The details of how to do it without interfering with any existing arguments largely depend on the specific use case.

        Mmm, I wasn't questioning the localisation per-se, but the fact that your use of local (pun unavoidable:-) doesn't localise a global variable - which the docs say it does/should - rather, it purports to declare a global variable, which AFAICT, you can't from within non-global scope.

        All that being said, it does rather assume that global is seen as a true global i.e. a package global variable c/w a variable declared to be accessible from the point of declaration down...

        There now, you should be as confused as I am ;-)

        A user level that continues to overstate my experience :-))
        What about this: It definitely isn't global, although it is shared between the two functions.
        { my %familySecrets; sub s1 { # Read family secrets } sub s2 { #write family secret #call s1 } }

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (13)
As of 2014-10-01 13:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    What is your favourite meta-syntactic variable name?














    Results (18 votes), past polls