Mechanical Transformation of Monadic Simple D-functions into Derived Functions
------------------------------------------------------------------------------
The following functions are said to be "extensionally equal" as, given any array
argument, each returns the same result.

    {⍬⍴⍴⍵}      ⍝ D-function for first-of-shape.

    ⍬∘⍴∘⍴       ⍝ Derived function for first-of-shape.

For very small functions, either coding may be appropriate, though for more com-
plex ones, the first style is probably preferable.

Having  said  this,  it is possible to prescribe a set of rules for transforming
(a subset of) simple monadic D-functions into derived functions.

NB:  There seems to be little practical value in performing this transformation,
other than  as an entertainment.  One possible exception is that primitive power
operator ⍣ may derive the inverse of a derived function, whereas D-functions are
not currently admitted.                                                     <V>

The  following  rules may be applied repeatedly to transform a simple monadic D-
function into a derived function:

    [0]     { f ⍵} → f
    [1]     a f ⍵} → a∘f ⍵}
    [2]     ⍵ f a} → (f∘a) ⍵}
    [3]     ⍵ f ⍵} → f⍨ ⍵}
    [4]     f f ⍵} → f∘f ⍵}
    [5]     f f a} → f (f a)
    [6]   (X) f ⍵} → ⍵ f⍨ X}
    [7]   (X) f a} → (f∘a) X}

where:

    a is an array
    f is a (possibly derived) function
    X is an array-returning expression

In  the  following  examples  "n→"  means "transforms using rule[n] to:" and the
pattern of the underlined tokens selects which rule to apply next.
               ¯¯¯¯¯¯¯¯¯¯
        {(⊂⍋⍵)⌷⍵}           ⍝ sort (Phil Last)
         ¯¯¯¯¯¯¯¯
    6→  {⍵⌷⍨⊂⍋⍵}
            ¯¯¯¯
    4→  {⍵⌷⍨⊂∘⍋⍵}
          ¯¯¯¯¯¯¯
    4→  {⍵⌷⍨∘⊂∘⍋⍵}
         ¯¯¯¯¯¯¯¯¯
    3→  {⌷⍨∘⊂∘⍋⍨⍵}
        ¯¯¯¯¯¯¯¯¯¯
    0→   ⌷⍨∘⊂∘⍋⍨


        {(+/⍵)÷⍴⍵}          ⍝ mean item of vector ⍵
              ¯¯¯¯
    4→  {(+/⍵)÷∘⍴⍵}
         ¯¯¯¯¯¯¯¯¯¯
    6→  {⍵ ÷∘⍴⍨ +/ ⍵}
           ¯¯¯¯¯¯¯¯¯¯
    4→  {⍵ ÷∘⍴⍨∘(+/) ⍵}
         ¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    3→  {÷∘⍴⍨∘(+/)⍨⍵}
        ¯¯¯¯¯¯¯¯¯¯¯¯¯
    0→   ÷∘⍴⍨∘(+/)⍨

Regarding rule [6]:  if expression X in (X) does not include an occurrence of ⍵,
an optimisation is to apply rule [1] instead.  This generally leads to a simpler
derived  function  (although  see the section on optimisation in "Extensions and
Restrictions" below):

        {(⊂⍬),⍵}        ⍝ (⊂⍬) does not contain ⍵, so apply rule [1].
         ¯¯¯¯¯¯¯
    1→  {(⊂⍬)∘,⍵}
         ¯¯¯¯¯¯¯¯
    0→   (⊂⍬)∘,

as opposed to:

        {(⊂⍬),⍵}        ⍝ ignore optimisation: apply rule [6].
         ¯¯¯¯¯¯¯
    6→  {⍵,⍨⊂⍬}
          ¯¯¯¯¯
    5→  {⍵,⍨(⊂⍬)}
         ¯¯¯¯¯¯¯¯
    2→  {(,⍨∘(⊂⍬))⍵}
        ¯¯¯¯¯¯¯¯¯¯¯¯
    0→    ,⍨∘(⊂⍬)

Prior to the transformations, the D-function must be pre-processed to remove:

[1] array strands that include an ⍵:

    ... A ⍵ B ... → ... (⊂A),(⊂⍵),(⊂B) ...

    For example:

        {⍵ ⍵}               ⍝ dup[licate]
         ¯¯¯
     →  {(⊂⍵),⊂⍵}
             ¯¯¯¯
    4→  {(⊂⍵),∘⊂⍵}
         ¯¯¯¯¯¯¯¯¯
    6→  {⍵,∘⊂⍨⊂⍵}
          ¯¯¯¯¯¯¯
    4→  {⍵,∘⊂⍨∘⊂⍵}
         ¯¯¯¯¯¯¯¯¯
    3→  {,∘⊂⍨∘⊂⍨⍵}
        ¯¯¯¯¯¯¯¯¯¯
    0→   ,∘⊂⍨∘⊂⍨

[2] square-brackets:

    A[B;C] → B C ⌷ A        ⍝ index brackets

    ↓[1] ... → ↓⍉ ...       ⍝ axis brackets

Restrictions and Extensions
---------------------------
[1] This  process doesn't cope with an expression that contains ⍵ as the operand
    of an operator:

        {(⊂⍣⍵)'Doh'}

[2] Nor will it transform a recursive call ∇.  Although it seems likely (to JMS)
    that  rules  might  be discovered for replacing some cases of recursion with
    the power operator ⍣.

[3] For multi-line dfns,  Phil Last has shown us how to transform a guard into a
    simple expression using /. See, for example →pow← and →cond←.

        [8] C:T⋄F}  →  ⊃{F}/(⍳~C),{T}/(⍳C),⊂⍵}

    where C, T and F are expressions. Unfortunately, guard expression C is eval-
    uated twice.

    (muse:

        There was overwhelming cultural pressure, in the specification of primi-
        tive power operator ⍣, for the "repeat count" to be the right _operand_.

        Had  the  repeat count been assigned to the left _argument_ of a monadic
        operator, as in →pow←, rule [8] could have been the simplified slightly:

        [8] C:T⋄F}  →  (~C){F}⍣ C{T}⍣ ⍵}

        Oh, and the _monadic_ derived function could have been "fixpoint":

            1∘+∘÷ ⍣ 1       ⍝ 1+÷ 1+÷ ... 1
        1.618033989
    )

(muse:

    JMS has a feeling that, without Hooks, Forks or an equivalent mechanism, the
    transformation of _dyadic_ dfns into derived functions might be significant-
    ly more difficult. But he's been wrong before.
)

It  might be interesting to provide a second set of post-transformation optimis-
ation rules such as:

    [o1]    f⍨⍨     → f
    [o2]    f⍨∘a    → a∘f
    [o3]    a∘(f⍨)  → f∘a
    ...

Rule [o2] would render choosing between rules [1] and [6], in the case (a) f ⍵},
unnecessary as either would (eventually) produce the same result:

        {(⊂⍬),⍵}        ⍝ (⊂⍬) does not contain ⍵, so apply rule [1].
         ¯¯¯¯¯¯¯
    1→  {(⊂⍬)∘,⍵}
         ¯¯¯¯¯¯¯¯
    0→   (⊂⍬)∘,

as opposed to:

        {(⊂⍬),⍵}        ⍝ ignore optimisation: apply rule [6].
         ¯¯¯¯¯¯¯
    6→  {⍵,⍨⊂⍬}
          ¯¯¯¯¯
    5→  {⍵,⍨(⊂⍬)}
         ¯¯¯¯¯¯¯¯
    2→  {(,⍨∘(⊂⍬))⍵}
        ¯¯¯¯¯¯¯¯¯¯¯¯
    0→    ,⍨∘(⊂⍬)
          ¯¯¯¯¯¯¯
    o2→  (⊂⍬)∘,         ⍝ (same derived function as above)

See also: dft

Back to: contents

Back to: Workspaces

Trouble seeing APL font?