in reply to How to access a variable inside subroutine?

As an alternative to the state keyword for turning your subroutine into a coroutine (a function that maintains state between calls), here is how you use a closure to effectively maintain a state variable declared outside of the counter subroutine and provides access to the current value of $add via subroutine "getter". In this way, $add is read only and only affected via counter. The ADD_COUNTER_CLOSURE: is simply a label handy in this case for self documenting the existence of the closure itself.
ADD_COUNTER_CLOSURE: { # $add is not accessible outside of closure, but # you do the 'getter', "add" which has access to $add my $add = 0; sub counter { my @nums = (1..500); for my $num(@nums) { $add += $num } } # getter sub add { return $add; } } # $add is not accessible directly here, must use add subroutine my $add = add; print qq{$add\n}; # increment $add via closure() counter(); $add = add; print qq{$add\n};

Output:

0 125250

Replies are listed 'Best First'.
Re^2: How to access a variable inside subroutine?
by pryrt (Abbot) on Sep 05, 2020 at 20:43 UTC
    I had an idea when you used the pre-state closure idea: put your getter inside the context of counter, so it that $add is in scope:

    use 5.030; use strict; use warnings; sub counter { my @nums = (1..500); state $add = 0; for my $num (@nums) { $add += $num; } sub getter { $add } # because this sub is inside the scope of coun +ter(), it has visibility on $add! } counter(); say "getter => ", getter();

      Side note: be careful doing this with a my variable because some weird things can happen with nested subs referencing lexicals from the enclosing scope. Look for Variable "%s" will not stay shared in perldiag.

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        I wanted to give the same warning and I'm not sure this is less of a problem with state

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

      Hi,

      Thank you!! It worked!!....I have always been baffled by the "getter/setter" stuff...I still don't understand it, but still was able to run the code you wrote.

        Generically speaking, "getters and setters" are any routine that you can (must ...) call to affect a value that you can't access directly – because it is inside of a closure or an object. In the general sense, they often have "side effects." For instance, calling a "color setter" actually causes the color of something to change, and also completely conceals the mechanics of how that actually happens.
      Very nice, thank you. I was going old school but now this is a lot cleaner and more concise.
        Read the link pointed out by LanX. Best way to learn it is to play around with it.

        Oops replied to the wrong thing. pritesh_ugrankar this message applies to your comment about it now working but you not understanding.