A note on reduction in Dyalog APL
Reduce
In APL, reduce f⌿
on a vector (1D array) can be thought
as evaluating the vector with f
inserted between adjacent
elements.
f⌿ a b c d
←→ a f b f c f d
←→ a f (b f (c f d))
The last ←→
shows that APL evaluates from right to left.
As a result, f⌿
is right reduce (or right fold).
As long as f
is commutative, like +
, the
result of right reduce is the same as the one from left reduce. But when
f
is not commutative, like ,
(concatenate),
the result would be different. The good news is that left reduce can be
expressed in term of right reduce.
((a f b) f c) f d
←→ d f⍨ (c f⍨ (b f⍨ a))
←→ d f⍨ c f⍨ b f⍨ a
←→ f⍨⌿ d c b a
←→ f⍨⌿⌽ a b c d
Here, f⍨
is the function f
with its left
and right arguments swapped, and ⌽
reverses its right
argument.
Windowed reduce
In fact, f⌿
is ambivalent, meaning it can be monadic or
dyadic. When used dyadically, f⌿
takes an integer as its
left argument. Now, f⌿
is windowed reduce. That
is, x f⌿ y
reduces every window of length x
with f
.
3 f⌿ a b c d
←→ (f⌿ a b c) (f⌿ b c d)
←→ (a f (b f c)) (b f (c f d))
Windowed right reduce can be written in terms of its left counterpart as well.
((a f b) f c) ((b f c) f d)
←→ (c f⍨ b f⍨ a) (d f⍨ c f⍨ b)
←→ (f⍨⌿ c b a) (f⍨⌿ d c b)
←→ ⌽ (f⍨⌿ d c b) (f⍨⌿ c b a)
←→ ⌽ 3f⍨⌿ d c b a
←→ ⌽ 3f⍨⌿ ⌽ a b c d
When the left argument is negative, the windows are reversed before the reductions.
¯3 f⌿ a b c d
←→ (f⌿⌽ a b c) (f⌿⌽ b c d)
←→ (f⌿ c b a) (f⌿ d c b)
←→ (c f (b f a)) (d f (c f b))
This is useful when one wants to calculate adjacent difference.
¯2 -⌿ 1 1 2 3 5 8 13 21
0 1 1 2 3 5 8
Here is how the negative case is related to the positive case.
¯3 f⌿ a b c d
←→ (f⌿ c b a) (f⌿ d c b)
←→ ⌽ (f⌿ d c b) (f⌿ c b a)
←→ ⌽ 3 f⌿ d c b a
←→ ⌽ 3 f⌿ ⌽ a b c d
In general, ⌽ x f⌿ v ←→ (-x) f⌿ ⌽ v
.
This means windowed right reduce can also be represented using windowed reduce with negative left argument.
((a f b) f c) ((b f c) f d)
←→ ⌽ 3 f⍨⌿ ⌽ a b c d
←→ ¯3 f⍨⌿ a b c d
You can try these equations here.