3

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.

Martin Ueding
  • 265
  • 1
  • 8
  • 3
    Take a look at this question and answers therein: https://mathematica.stackexchange.com/questions/10432/how-to-avoid-nested-with - 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) – Lukas Lang Aug 14 '19 at 08:58

2 Answers2

1

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]
mikado
  • 16,741
  • 2
  • 20
  • 54
1

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]&)
SHuisman
  • 3,258
  • 8
  • 12