3
$\begingroup$

I sometimes want to write a function which needs to apply a bunch of transformations that are not functions of a single parameter only:

f[x_] := h[g3[g2[g1[x, 37], Some -> Stuff], "foo"], "bar"];

I find this hard to read code. And I would like to give names to the intermediate results.

If these were single parameter functions one could just write f = h @* g3 @* g2 @* g1 but that does not work in this case. One could try to curry away the additional parameters, but sometimes the some other intermediate result needs to be used again.

Ideally I would like to have the following which just sets the a, b and c as values but allows me to have subsequent values depending on preceeding ones, so exacly what With will not let me do.

f[x_] := specialScope[
   {a = g1[x, 37],
    b = g2[a, Some -> Stuff],
    c = g3[c, "foo"]},
   h[c, "bar"]];

My current solution is to use Module, but I think that it creates more overhead than needed as the variables do not need to be mutable within the scope.

f[x_] := Module[
   {a, b, c},
   a = g1[x, 37];
   b = g2[a, Some -> Stuff];
   c = g3[c, "foo"];
   h[c, "bar"]];

Is there something like that? I believe that Haskell's where supports this use case.

$\endgroup$
1
  • 3
    $\begingroup$ Take a look at this question and answers therein: mathematica.stackexchange.com/questions/10432/… - I frequently use the LetL function by @LeonidShifrin from there. Other alternatives are the GeneralUtilities`Where function and the undocumented form of With (see answer by @MichaelE2 there) $\endgroup$
    – Lukas Lang
    Commented Aug 14, 2019 at 8:58

2 Answers 2

1
$\begingroup$

An alternative approach. You could rewrite your function

f[x_] := h[g3[g2[g1[x, 37], Some -> Stuff], "foo"], "bar"];

as

f[x_] := h["bar"][g3["foo"][g2[Some -> Stuff][g1[37][x]]]]

or more legibly

F = h["bar"]@*g3["foo"]@*g2[Some -> Stuff]@*g1[37]
$\endgroup$
1
$\begingroup$

Another way of doing this would be using Fold:

Fold[First[#2][#1, Last[#2]] &, x, {{g1, 37}, {g2, Some -> Stuff}, {g3, "foo"}, {h, "bar"}}]

So the function and the other arguments are paired visually…

Or one can create an operator form using Composition:

(h[#,"bar"]&)@*(g3[#,"foo"]&)@*(g2[#,Some->Stuff]&)@*(g1[#,37]&)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.