MergeFunctions

Description

MergeFunctions is an illustration that very simple code can perform reasonably general tasks.  It can be described thusly:

	Take every Function[body] that occurs as a subexpression and eliminate the Function head, and wrap Function around the entire resulting expression.

This is on the assumption that the local variables in body, i.e. #n and ##n, are all meant to be part of the whole.

Definition

MergeFunctions::usage = "MergeFunctions[functional] takes an \
expression
containing several pure functions and merges them so that 'functional'
becomes a single operator."

MergeFunctions[functional_] := 
      Replace[Function[functional], Function[body_] :> body, -1, 
        Heads -> True]

Some simple examples

MergeFunctions[functional_] := 
      Replace[Function[functional], Function[body_] :> body, -1, 
        Heads -> True]

Example 1

functional  =  (f[#1] &) / (1  +  (g[#2] &)^2)

func  =  MergeFunctions[functional]

func[x,  y]

Example 2

functional  =  f[#1] &/
          Sqrt[g[#1,  #2] &] +  (h[#2,  ##3,  #1] &)^2

func  =  MergeFunctions[functional]

func[x,  y,  z]

Example 3

functional  =  Identity[#] &  +  (D[#,  
              x] &)  +  (Integrate[#,  x] &)

func  =  MergeFunctions[functional]

func[ArcTan[x]]

Compare to Through, which in such a simple case doesn't need Identity to be an explicit pure function:

Through[
      Identity  +  (D[#,  x] &)  +  (Integrate[#,  
              x] &)]

This is only because Through is so specific about where the functions are assumed to reside:  the level 1 elements of the expression.

Certainly a more industrial-strength version of this could be written.

It could recognize nested pure functions, probably treating the inner functions as independent of the whole, and thus not meant to participate in the merging.

Perhaps it should treat #0 specially ... or perhaps not.

It could handle Function's that use named dummy variables, i.e. Function[{x1, x2, ...}, body, attrs], instead of Slot variables.  A mixture of Function's, some with Slot variables and some with named variables, could be merged, using #n for the variables in the final function.

MergeFunctions does not subsume the built-in Through function, as it considers only explicit pure functions (...) & for merging.  Thus, for instance, a symbol such as Identity or Sin which represents a function is not taken into account by this.  If you want such non-explicit pure functions to be considered functions, then write them in explicit forms such as Sin[#]& or f[##]&.