in reply to loop over n-dimensional lattice

See also List::Comprehensions.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

Replies are listed 'Best First'.
Re^2: loop over n-dimensional lattice
by 0AP0 (Initiate) on Aug 05, 2008 at 22:15 UTC
    To clarify-- It looks to me like the A::L::NestedLoops method lets me execute code directly within the nested loops where the List::Comprehensions method lets me generate a list of parameter values that I would then feed into my function as a second step. Do I have that right?

      No. A::L::NestLoops provides an iterator; List::Comprehensions takes a callback.

      By way of example, you mentioned iterating an N-dimensional 'lattice', (by which I assume you mean 'array'), that you don't know how many dimensions it will have until runtime. If you run the following code it will select a 2,3, or 4 dimension array at random and then iterate it printing out the indices and values:

      #! perl -slw use strict; use List::Comprehensions; sub expandDims { return unless ref $_[ 0 ] eq 'ARRAY'; return [ 0 .. $#{ $_[ 0 ] } ], expandDims( $_[ 0 ][ 0 ] ); } my $ref2D = [ map [ 0 .. 2 ], 0..3 ]; my $ref3D = [ map [ map [ 0..1 ], 0..2, ], 0..3 ]; my $ref4D = [ map [ map [ map [ 0..1 ], 0..2, ], 0..3 ], 0..4 ]; my $ref = ( $ref2D, $ref3D, $ref4D )[ rand 3 ]; comp1 { my $val = $ref; $val = $val->[ $_ ] for @_; printf "[%s] := %s\n", join('][', @_), $val; } expandDims( $ref );

      The output looks like this:

      c:\test>junk4 [0][0] := 0 [0][1] := 1 [0][2] := 2 [1][0] := 0 [1][1] := 1 [1][2] := 2 [2][0] := 0 [2][1] := 1 [2][2] := 2 [3][0] := 0 [3][1] := 1 [3][2] := 2 c:\test>junk4 [0][0][0] := 0 [0][0][1] := 1 [0][1][0] := 0 [0][1][1] := 1 [0][2][0] := 0 [0][2][1] := 1 [1][0][0] := 0 ... [3][0][0] := 0 [3][0][1] := 1 [3][1][0] := 0 [3][1][1] := 1 [3][2][0] := 0 [3][2][1] := 1 c:\test>junk4 [0][0][0][0] := 0 [0][0][0][1] := 1 [0][0][1][0] := 0 [0][0][1][1] := 1 [0][0][2][0] := 0 ... [4][3][0][0] := 0 [4][3][0][1] := 1 [4][3][1][0] := 0 [4][3][1][1] := 1 [4][3][2][0] := 0 [4][3][2][1] := 1

      Not very interesting, but it demonstrates both discovering the dimensions of the AoA(...) at runtime and then iterating it.

      There is a flaw in L::C, relative to FP language equivalents. Namely, that although it will accept multiple 'guard' subs interspersed with the array refs as input, the guard sub are called en-masses with all the generated arguments just prior to the main callback. In (for example) Haskell, the guard subs are called in their input order with just the arguments that precede (right to left) them in the input list.

      The advantage of A::Ls iterator is that you can abandon the iterator at any time, where L::Cs callback will be called for the entire set of combinations. Though you can suppress entry to the main callback by returning nothing from a guard sub. For example, if you change last line of the code above to this:

      } sub{ "@_" =~ /2/ ? () : @_ }, expandDims( $ref );

      Then the main callback code will not be called if any of the indices is a 2. For the 2D array, the output then becomes:

      c:\test>junk4 [0][0] := 0 [0][1] := 1 [1][0] := 0 [1][1] := 1 [3][0] := 0 [3][1] := 1

      The main advantage (for me) of L::C is that I find the syntax more amenable to the way I think.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        No. A::L::NestLoops provides an iterator; List::Comprehensions takes a callback.

        While NestedLoops does provide an iterator, it also accepts a callback.

        my $iter = NestedLoops(\@loops);
        or
        NestedLoops(\@loops, \&callback);
        A big help. Thanks. I used "lattice" to refer to the mathematical construct that I care about instead of "array" which is a data structure that I could be easily convinced to ditch for something better. Apologies if it muddled the question.