rslt ← {larg} {''} ##.vof F vof G vof ··· rarg ⍝ Vector of functions. From Phil Last: [vof] simulates the distribution of a "vector of functions" among the items of its argument(s). It can be illustrated by the practical problem: "What is the size of the rectangle that bounds these three rectangles, with B and C side-by- side and below A?". ┌──────────────────────────┐ │ A │ │ │ ├────────────┬─────────────┴──┐ │ │ │ │ │ C │ │ B │ │ │ │ │ │ ├────────────────┘ │ │ └────────────┘ The answer is: ((1↑⍴A) + (1↑⍴B) ⌈ (1↑⍴C)) , (¯1↑⍴A) ⌈ (¯1↑⍴B) + (¯1↑⍴C) but it would be much nicer to be able to say: (⍴A) (+⌈) (⍴B) (⌈+) (⍴C) A diagram shows the distribution of functions with respect to argument items: ┌─────┬────────┬─────┬────────┐ │ │ │ │ │ (⍴A)[0 1] (+⌈) (⍴B)[0 1] (⌈+) (⍴C)[0 1] │ │ │ │ │ └────┴─────────┴────┴─────────┘ where (+⌈) and (⌈+) are both 2-item "function vectors" to be distributed over their 2-item argument(s). Compare this with the way that a vector of namespace references in a function expression, distributes its function over its arguments without needing to specify each: (ref0 ref1 ref2 ref3).{···w} ⍳4 More generally: a b c···(f g h···) x y z··· ←→ (a f x)(b g y)(c h z)··· ⍝ vector vector (⊂a) (f g h···) x y z··· ←→ (a f x)(a g y)(a h z)··· ⍝ scalar vector a b c···(f g h···) ⊂x ←→ (a f x)(b g x)(c h x)··· ⍝ vector scalar (⊂a) (f g h···) ⊂x ←→ (a f x)(a g x)(a h x)··· ⍝ scalar scalar (f g h···) x y z··· ←→ (f x)(g y)(h z)··· ⍝ monadic vector (f g h···) ⊂x ←→ (f x)(g x)(h x)··· ⍝ monadic scalar [vof] implements the distributive function vector in the alternating mode we have seen with →of←, →case← and →lof←. {a b c ···} {''} vof f vof g vof h ··· x y z As with →lof← we need (except in special circumstances) the closing call with the null function. An alternative would be to provide a slightly different "special" coding for the leftmost operator: _vof←{ ⍝ Close vector of functions. ⍺←⊂ ⍝ ⍺ elided: ⊂⍵. (al ar)(wl wr)←⍺ ⍵ ⍝ distrubute arg(s). 1≡⍺ 1:(⍺⍺ wl)(⍵⍵ wr) ⍝ mondadic. (al ⍺⍺ wl)(ar ⍵⍵ wr) ⍝ dyadic. } Although more expensive, the following coding works without a terminator to the left. The control over the iteration is the length of the data so if the number of functions is different it goes wrong as do the others. Uses the same method of self reference as the coding of fk in →fork←: vof←{ (M D)←112358314594370 774156178538190 ⍺←M (m d)←M D∊⊂⍺ e←2∊⍴⍵ e<m:(M ⍺⍺ ¯1↓⍵),⊂⍵⍵⊃⊢/⍵ e<d:(D ⍺⍺ ¯1↓⍵),⍵⍵/⊃⊢/⍵ e∧m:⊃⍺⍺{(⍺⍺ ⍺)(⍵⍵ ⍵)}⍵⍵/⍵ e∧d:⊃⍺⍺{(⍺⍺/⍺),⍵⍵/⍵}⍵⍵/⍵ D ∇ ⍺{⍺ ⍵}¨⍵ } Examples: 1 2 3 4 {''} vof + vof ! vof ? vof | 5 6 7 8 ⍝ vector vector 6 15 1 6 4 0 4 {''} vof + vof ! vof ? vof | 5 6 7 8 ⍝ scalar vector 9 15 4 2 1 5 0 1 2 3 4 {''} vof + vof ! vof ? vof | 5 ⍝ vector scalar 6 10 4 5 2 1 4 {''} vof + vof ! vof ? vof | 5 ⍝ scalar scalar 9 5 3 5 1 4 1 {''} vof + vof ! vof ? vof | 5 6 7 8 ⍝ monadic vector 5 720 1 8 {''} vof + vof ! vof ? vof | 5 ⍝ monadic scalar 5 120 2 5 {2⍴⍵} vof {3⍴⍵} vof {4⍴⍵} 2 3 4 ⍝ without left closure ┌─┬─┬─────┬───────┐ │2│2│3 3 3│4 4 4 4│ └─┴─┴─────┴───────┘ {⍬} vof {2⍴⍵} vof {3⍴⍵} vof {4⍴⍵} 2 3 4 ⍝ explicit left closure ┌───┬─────┬───────┐ │2 2│3 3 3│4 4 4 4│ └───┴─────┴───────┘ {2⍴⍵} _vof {3⍴⍵} vof {4⍴⍵} 2 3 4 ⍝ closure using [_vof] ┌───┬─────┬───────┐ │2 2│3 3 3│4 4 4 4│ └───┴─────┴───────┘ Notice that the length of the result is the number of functions, not necessarily the length of the argument(s). See also: case of lof Function_arrays co_ops Back to: contents Back to: Workspaces