in reply to Re^2: Access a global variable from a subroutine when used as "for" iterator
in thread Access a global variable from a subroutine when used as "for" iterator

You are right... my demo was to present what I found. In the real code, the equivalent to show() function receives a parameter, but under certain conditions, I wanted it to default to the iterator.

  • Comment on Re^3: Access a global variable from a subroutine when used as "for" iterator

Replies are listed 'Best First'.
Re^4: Access a global variable from a subroutine when used as "for" iterator
by LanX (Saint) on Dec 21, 2023 at 02:44 UTC
    We really need to know more for a good advice. For instance, do you plan to export that function?

    For instance:

    Another possibility it's a second closure function to set this closure variable.

    Yet another is using a full qualified $private::package::var

    In short: TIMTOWTDI, but it depends.

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

      The full story is that I'm parsing some documents in Excel spreadsheets and I just wanted to simplify the expresions, so the list c('A1'),c('A'),c('B') just means that the value at the constant cell A1 is followed by the values of columns A and B at the "current row" in the details area, without having to include the iterator variable as in c('A',1),c('A',$i),c('B',$i) (which is also supported). The problem was that I always got the values at a fixed row based on the previous value of the iterator variable when it was not explicit as an argument, either as c('A',$i) or c("A$i").

      Of course, there are also some helper functions to get formated values. For instance, d('A',1) internally calls c(@_) and returns a date properly formatted (and not an epoch number). As there could be many levels of nested functions, I decided to use a global variable and avoid the optional parameter.

      Now I know that for over lists does a special treatment on the iterator variable, probably because of a perl 4 inheritance, and I should use a C-like for or a while construct when using a global variable as iterator from subroutines called from the loops, but for the moment, I'm using this construct:

      my $row = 0; for (2..10) { $row = $_; gen(d('A1'), c('A'), c('B'), t('C'), c('D')+c('E')); }

      I think it is much more clear and easy to maintain when the spreadsheet changes than:

      my $row = 0; for ($row = 2, $row <= 10; $row++) { gen(d('A',1), c('A',$row), c('B',$row), t('C',$row), c('D',$row)+c(' +E',$row)); }

      Now I see that if I had declared the global variable without an initial value of zero, an error should have been raised and saved many hours trying to identify why I got wrong values from the spreadsheet. >:-(

        OK, there are some ambiguities in your description, so I'm not sure I understand your intentions in total.

        Your perception of my as global is also wrong !

        In your case I'd suggest using package vars, because you can easily access the vars after exporting the subs.

        The following demo is explicitly using two packages to fake an import situation. you can simplify it in a one-file-for-all situation. But it should help you grasp the differences between different var types.

        use v5.14; use warnings; { package _csv; # some package name our $row; our $col; sub c { my $c = shift // $col // die "col undefined"; my $r = shift // $row // die "row undefined"; say "c:$c r:$r"; } say "--- inside same scope"; for $row (1..3) { c("A"); } } package main; BEGIN { *c = \&_csv::c } # fake import for demo say "--- one default"; for $_csv::row (1..3) { c("B"); } say "--- two defaults"; for $_csv::col ("C".."D") { for $_csv::row (4..5) { c(); } } say "--- explicit local "; { local $_csv::row = 10; c("E"); c("F"); } say "--- defaults were localized inside loop"; c("G");

        perl ~/perl/cell_dsl.pl --- inside same scope c:A r:1 c:A r:2 c:A r:3 --- one default c:B r:1 c:B r:2 c:B r:3 --- two defaults c:C r:4 c:C r:5 c:D r:4 c:D r:5 --- explicit local c:E r:10 c:F r:10 --- defaults were localized inside loop row undefined at /home/lanx/perl/cell_dsl.pl line 12.

        But frankly, if I were you, I'd rather define multiple subs with special explicit behavior instead of overloading one with implicit DWIM.

        Or at least, use them both together and let the implicit one call the explicit ones.

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