For-loops
Given an initial state defined by a number of variables, a for-loop iterates through its argument array modifying the state.
A←... ⋄ B←... ⋄ C←... ⍝ initial state
:For item :In items ⍝ iterating through array "items"
A←A ... item ⍝ new value for A depending on item
C←C ... A ... item ⍝ new value for C depending on A and item
... ⍝ state updated
:EndFor
A B C ⍝ final state
In the above example the state comprises just three variables. In general, it may be arbitrarily complex, as can the interactions between its various components within the body of the loop.
Dfns
Dfns don’t have for-loops. Instead, we can use reduction (or “fold”) with an accumulating vector “tuple” of values representing the state. Here is the D-equivalent of the above code:
⊃{ ⍝ next item is ⍺
(A B C)←⍵ ⍝ named items of tuple ⍵
A∆←A ... ⍺ ⍝ new value for A depending on item ⍺
C∆←C ... A∆ ... ⍺ ⍝ new value for C depending on A∆ and item ⍺
... ⍝ ...
A∆ B C∆ ⍝ "successor" tuple (A and C changed)
}/(⌽items),⊂A B C ⍝ for each item and initial state tuple A B C
In this coding, the accumulating tuple arrives as the right argument (⍵) of the operand function, with the next “loop item” on the left (⍺). Notice how the items vector is reversed (⌽items
) so that the items arrive in index-order in the right-to-left reduction.
If you prefer your accumulator to be on the left, you can replace the primitive reduction operator (/) with Phil Last’s foldl operator, which also presents its loop items in index-order:
foldl←{⊃⍺⍺⍨/(⌽⍵),⊂⍺} ⍝ fold left
then:
A B C { ⍝ final state from initial state (left argument)
(A B C)←⍺ ⍝ named items of tuple ⍺
A∆←A ... ⍵ ⍝ new value for A depending on item ⍵
C∆←C ... A∆ ... ⍵ ⍝ new value for C depending on A∆ and item ⍵
A∆ B C∆ ⍝ successor tuple (A and C changed)
} foldl items
If the number of elements in the state tuple is large, it can become unwieldy to name each on entry and exit to the operand function. In this case it simplifies the code to name the indices of the tuple vector, together with an at operator to denote the items of its successor:
T ← (...) (...) ... ⍝ intitial state tuple T
A B C D ... ← ⍳⍴T ⍝ A B C D ... are tuple item "names"
T { ⍝ final state from initial state (left argument)
A∆←(A⊃⍺) ... ⍵ ⍝ new value for A depending on item ⍵
C∆←(C⊃⍺) ... A∆ ... ⍵ ⍝ new value for C depending on A∆ and item ⍵
A∆ C∆(⊣at A C)⍺ ⍝ successor tuple (A and C changed)
} foldl items
where:
at←{A⊣A[⍵⍵]←⍺ ⍺⍺(A←⍵)[⍵⍵]} ⍝ (⍺ ⍺⍺ ⍵) at ⍵⍵ in ⍵
There is some discussion about providing a primitive operator @ for at in Dyalog V16.
Examples
Function kk illustrates naming tuple elements (S E K Q) at the start of the operand function.
Function scc accesses tuple elements using named indices (C L X x S) and an at operator.
Tuples: a postscript
We might define a “tuple” in APL as a vector in which we think of each item as having a name, rather than an index position.
bob ⍝ Tuple: name gender age
┌───┬─┬──┐
│Bob│M│39│
└───┴─┴──┘
folk ⍝ Vector of tuples
┌──────────┬────────────┬──────────┬────────────┬─
│┌───┬─┬──┐│┌─────┬─┬──┐│┌───┬─┬──┐│┌─────┬─┬──┐│
││Bob│M│39│││Carol│F│31│││Ted│M│31│││Alice│F│32││ ...
│└───┴─┴──┘│└─────┴─┴──┘│└───┴─┴──┘│└─────┴─┴──┘│
└──────────┴────────────┴──────────┴────────────┴─
↓⍉↑ folk ⍝ Tuple of vectors
┌─────────────────────────┬────────┬───────────────┐
│┌───┬─────┬───┬─────┬─ │MFMF ...│39 31 31 32 ...│
││Bob│Carol│Ted│Alice│ ...│ │ │
│└───┴─────┴───┴─────┴─ │ │ │
└─────────────────────────┴────────┴───────────────┘
⍪∘↑¨ ↓⍉↑ folk ⍝ Tuple of matrices
┌─────┬─┬──┐
│Bob │M│39│
│Carol│F│31│
│Ted │M│31│
│Alice│F│32│
... . ..
└─────┴─┴──┘
APLers sometimes talk about “inverted files”. In this sense, a “regular” file is a vector-of-tuples and an inverted file (or more recently: “column store”) is a tuple-of-vectors (or matrices).