Any rule of thumb for converting a simple mathematical expression into a pure function?

By simple mathematical expression I mean one with a few functions and few variables copied into MMA in a mechanical way from a math book. For example this one, giving the distance between two points in a rectangular cartesian coordinate plane:

u = {-3, 3}; v = {1, 5};
d = (( Abs[ u[[1]]] - Abs[v[[1]]] ) ^2 +  (Abs[u[[2]]] -
Abs[v[[2]]])^2  )^(1/2


Except for the use of the Abs built-in function (I found no way in InputForm to type in the vertical bars on each side of the variable which is possible in TraditionalForm ), you recognize at a glance what this is about with an elementary knowledge of MMA. Now I read in MMA documentations that it is advised to convert any "math-like" expression into a pure functions but apart from many examples suited to a specific expressions - mine is another sure - I did not read any guidelines which generalises the approach to take. So I proceeded in a an empirical way, a "down-up" up approach:

Abs[#] &@ {u, v}
Apply[Subtract[##] &, %, {1}]
(#^2) & [ %]
Sqrt[Apply[Plus[##] & , %]]


Only pure functions here which can be condensed by copy/pasting the origination expression in place of % like that :

Sqrt[Apply[
Plus[##] & , (#^2) & [
Apply[Subtract[##] &, Thread[Plus[Abs[#] &@ {u, v} ]], {1}]]]]


I'm sure that if I read this last expression in a week's time, I'll be perplexed unless I trace it! Is it easy to simplify this concatenation of 4 pure functions into one single pure function, and if so, how? I feel that the way the data is presented before you start writing MMA code is of prime importance: Instead of two lists, I could have used one list with sublists, or a flattened out list (ie {u1,u2,v1,v2) and each of this choice has a strong bearing to what you will code afterwards. Are there any guidelines about what is the less messy or more elegant in the way lists are to be constructed for a given problem?

-
In those more complicated cases consisting of multiple steps, using Composition clears things up for me while still retaining a pure functional style. –  Thies Heidecke Apr 27 '13 at 20:29
Part of being able to convert into idiomatic code also requires familiarity with the functions available in Mathematica (which only comes with practice). For instance, the function you're looking for is EuclideanDistance. In general, writing simpler, readable functions and chaining with Composition is much cleaner. –  The Toad Apr 27 '13 at 20:29
I don't think that's exactly the function the OP was looking for -- the Abs[ ] are in the wrong place to make it identical to EuclideanDistance. The function he's defined is a small variant: EuclideanDistance[Abs[u], Abs[v]] –  bill s Apr 27 '13 at 20:50
Yeah, i noticed that, too. I couldn't tell if the goal is to get a formula for euclidean distance or if the extra Abs is on purpose. –  Thies Heidecke Apr 27 '13 at 20:52
This is what I like about this question... I don't think it's really about the specific function, but about strategies for finding functions. I guess we found one: ask on StackExchange and get a bunch of answers! –  bill s Apr 27 '13 at 20:53

If the question is about converting general math-book expressions to pure functions, you could use something like

SetAttributes[convert, HoldAll];
convert[expr_, vars_List] :=
With[{variables = Unevaluated@vars},
Block[variables,
Evaluate@(Hold[expr] /. Thread[vars -> Slot /@ Range@Length@vars]) & // ReleaseHold
]]


To apply,

convert[Sqrt[(Abs[u[[1]]] - Abs[v[[1]]])^2 + (Abs[u[[2]]] - Abs[v[[2]]])^2], {u, v}]


and you get

Sqrt[(Abs[#1[[1]]] - Abs[#2[[1]]])^2 + (Abs[#1[[2]]] - Abs[#2[[2]]])^2] &


Alternative definition:

convert[expr_, vars_List] := Function @@@ Hold[{vars, expr}] // ReleaseHold


and the output would be the other kind of pure function:

Function[{u, v}, Sqrt[(Abs[u[[1]]] - Abs[v[[1]]])^2 + (Abs[u[[2]]] - Abs[v[[2]]])^2]]


Of course one could simply type that to begin with.

I'm not confident I understand the question. I'm not sure why one would want to de-compose a formula into component functions, but here are some variations à la @ThiesHeidecke's answer:

u = {-3, 3}; v = {1, 5};
Composition[Sqrt, Total, #^2 &, Subtract @@ # &, Abs[{##}] &][u, v]
(* 2 Sqrt[2] *)


Beware: Things go awry if u, v are not vectors. A way to avoid such a pitfall is

Composition[Sqrt, Total, #^2 &, Subtract @@ # &, Abs, Outer[Part, {##}, {1, 2}, 1] &][u, v]


But now this is limited to 2-dimensional vectors. If we abandon pure functions, we can define a function to handle all cases:

distAbs[u_?VectorQ, v_?VectorQ] :=
Composition[Sqrt, Total, #^2 &, Subtract @@ # &, Abs[{##}] &][u, v]


As others have pointed out, this particular function can be encoded less ornately as

EuclideanDistance @@ Abs[{##}] &


For other formulas, the following is straightforward and easily adapted:

distAbs[u_?VectorQ, v_?VectorQ] :=
Sqrt[(Abs[u[[1]]] - Abs[v[[1]]])^2 + (Abs[u[[2]]] - Abs[v[[2]]])^2];


I would not be surprised if this is the sort of thing you're looking for. This is the easiest way to make function out of a formula, even if the formula might be expressed more simply in terms of other Mathematica functions.

-

In those more complicated cases consisting of multiple steps, using Composition clears things up for me while still retaining a pure functional style. In your example of calculating the distance between two points in 2D i would write:

u = {-3, 3}; v = {1, 5};
Composition[Sqrt, #.# &, Subtract][u, v]

(* 2 Sqrt[5] *)


or as rm -rf pointed out you can just use the builtin

EuclideanDistance[u, v]

(* 2 Sqrt[5] *)


In case you want to incorporate the extra Abs to each parameter before calculating the distances you can unpack the parameters ## into a list, take the absolute value and rewrap it into a new Sequence before passing it to Subtract:

Composition[Sqrt, #.# &, Subtract, Sequence @@ Abs[{##}] &][u, v]

(* 2 Sqrt[2] *)


You could reuse those functions by binding them to a new symbol via Set and extract the idea of mapping a function onto every parameter, taking extra advantage of functions that are Listable, like Abs:

MapSequence[f_] := Sequence @@ f[{##}] &     /; MemberQ[Attributes[f], Listable]
MapSequence[f_] := Sequence @@ (f /@ {##}) &

AbsDistance = Composition[Sqrt, #.# &, Subtract, MapSequence[Abs]];
AbsDistance[u, v]
(* 2 Sqrt[2] *)

-
I like this answer, thanks. Does it make much difference if my input data is {{u},{v}} or {u1,u last,v1,...,v last}? I have other expressions than I one I gave in mind. –  Sigis K Apr 27 '13 at 21:48
Usually code gets easier to read and simpler when the data structure matches the structure of the objects you are dealing with. In this case the two vectors being represented by two lists. You surely could write code with the same functionality for a flattened out version of the data but it would probably be harder to read. But there's no right or wrong here. Often it's a tradeoff between readability and performance (e.g. vectorised operations are fast but can get hard to read if the vectors are flattened out versions of something different like trees for example). –  Thies Heidecke Apr 27 '13 at 22:55
Abs /@ {##} is more compactly done as Abs[{##}], due to listability. –  Guess who it is. Apr 28 '13 at 13:42
Thanks for pointing that out, i'll add that to the answer. –  Thies Heidecke Apr 28 '13 at 14:05
@J.M. Hmm... same number of characters :P (ok, Abs@{##}) –  The Toad Apr 28 '13 at 14:58

I know for me, I spent years using Matlab (or should I say, a toolbox-based computational system), where there is a trick called vectorization: you turn almost everything (ifs, ands, sums, products...) into simple vector commands. Doing this with your function is pretty natural since you've already defined the entries in terms of two vectors. You take the Abs of each entry, then subtract the two vectors, then take the Norm, hence

Norm[Abs[u] - Abs[v]]


If you happen (like rm -r) to know the function EuclideanDistance, this can also be used in place of Norm

EuclideanDistance[Abs[u], Abs[v]]


I guess the general strategy (or maybe it's really a tactic) is to keep things in vector (or should I say "List") form as long as possible, and try to avoid breaking them into individual elements. Recognizing that certain operations recur again and again (in this case we have Abs and Norm) is also key, though it's hard to know how to make this into a rule of thumb.

-

In my continuing mission to provide smartass answers, you can do, for example:

u = {-3, 3}; v = {1, 5};
d = Function[{u, v},
((Abs[u[[1]]] - Abs[v[[1]]])^2 + (Abs[u[[2]]] - Abs[v[[2]]])^2)^(1/2)][u, v]


I think the reason why it's suggested to convert to pure functions is for performance, otherwise I don't think I'd bother. But maybe there are other reasons to do it.

-
I don't think performance is the reason pure functions are used. I feel the main reason is functional programming. It's very convenient to make a pure function from an existing function by replacing one or more variables by Slot so that you can Map or Apply it over a list. –  Sjoerd C. de Vries Apr 27 '13 at 21:40