# Feedback on Functional Programming: Propagation of uncertainty

Lately I've been trying to use functional prgramming and tried to implement the gaussian propagation of uncertainty (without correlation) in an elegant way, here is the outcome:

Norm /@ (#2 Outer[(Derivative @@ #2)@f @@ #1 &, #1,
IdentityMatrix@Last@Dimensions@#1, 1] /. f -> #3) &[data, error, f]


data and error are assumed to be two dimensional lists (lists of data points), and f is a function. What bothers me a bit is the ReplaceAll (/.) rule for f, because I couldn't figure out how to create a function g in a way that Outer[g &, ...]& takes f as an argument to return a new function g[f]&, which again takes two arguments (here a partial derivative of f respect to the variable specified by the first argument, evaluated at a point specified by the second argument).

What I ask for basically is some feedback. What could be done better? Any suggestions are appreciated, merci.

• Well, I don't have any feedback on your code right now, but I implemented this already here (in fact, this question might even be considered a duplicate). Have a look and see what you think. – Oleksandr R. Feb 10 '13 at 23:24
• Mathematica 12 now has a built-in function called Around to handle this. – balping Apr 18 '19 at 1:37

The replace is unnecessary here. When I see this right, then your only issue is, that you use the slot #3 inside the inner pure function. There, it would be belong semantically to the inner function but you want it to be the parameter of the outer one.

This can be solved by using only for the inner function the (#...)& syntax. For the outer one, you use the full Function where you can name parameters. This should solve your problem and removes the ugly replace

Norm /@ Function[{dat, err, fun},
err Outer[(Derivative @@ #2)@fun @@ #1 &, dat,
IdentityMatrix@Last@Dimensions@dat, 1]][data, error, f]


The above should give the same result but is by far better readable since you don't have to search which Slot (#) belongs to which function.

I typically use With in cases such as this. Using With does not leave a stray reference to Globalf and it substitutes the value directly into the expression before evaluation, rather than after as your use of ReplaceAll does.

With[{f = #3},
Norm /@ (#2 Outer[(Derivative @@ #2)@f @@ # &, #, IdentityMatrix@Last@Dimensions@#1, 1])
] &[data, error, f]


I also note that given the statement: "data and error are assumed to be two dimensional lists" you can shorten IdentityMatrix@Last@Dimensions@#1 a bit by just checking the length of one of the elements: IdentityMatrix@Length@Last@#. If you wanted to "Golf" the code you could use DiagonalMatrix[#[]^0]`. :-)