4
$\begingroup$

I find myself recently writting, more often than not, code that makes heavy use of RightComposition eg.

expr//f/*g/*h

It is relatively straightforward to first operate on expr with f then apply g on the result and so on with operators like h etc.

It gets cumbersome, however, to operate on complicated expressions eg. head1[expr1,head2[expr2]]; also, performing contrived operations gets progressively hard to handle.

I find that the major drawback of writing one-liners like that, hits hardest when subsequent operations need input consumed by operators applied earlier on.

To tackle this problem I find myself making heavy use of Through eg.

expr//(Through[{Identity,f}[#]]&)/*Apply[g]

In the code snippet, g needs both expr and f[expr] as input and this is where Through comes in handy.

Carrying intermediate results to subsequent operators, in that fashion, proves equally cumbersome esp. when the chain of operations is long.

Trying to find a compromise that allows me to keep writting one-liners that are relatively easy to maintain, debug and help mitigate their downsides I came up with chainList:

chainList[expr_, fs__] := Fold[Join[#1,{#2@@#1}]&, {expr}, {fs}]

chainList resembles FoldList in that it returns a list of intermediate results eg.

chainList[x,f,g,h]

evaluates to

{x,f[x],g[x,f[x]],h[x,f[x],g[x,f[x]]]}

I have experimented with different implementations of chainList but I can't seem to find an implementation that performs faster than the one presented above.

It is true that speed is not so much of an issue for most of my practical needs as I rarely chain more than 5-7 operators in a line and operations are mostly structural modifications of the expressions involved; however I would like to find out if there's a better approach to handling one-liners and also if chainList can be improved.

$\endgroup$
7
  • $\begingroup$ "I rarely chain more than 5-7 operators in a line" - doesn't that hamper readability and maintainability of your code? $\endgroup$
    – MarcoB
    Jan 2, 2022 at 4:27
  • $\begingroup$ @MarcoB when I have to chain many operators, yes it does; not having to worry about their input makes things somewhat easier $\endgroup$
    – joka
    Jan 2, 2022 at 10:58
  • 1
    $\begingroup$ Perhaps this thread could give you some pointers. $\endgroup$
    – Syed
    Jan 2, 2022 at 17:39
  • $\begingroup$ @Syed thanks, ComposeList looks promising, also I didn't know ReverseApplied was a thing $\endgroup$
    – joka
    Jan 2, 2022 at 18:42
  • $\begingroup$ I never understood what is the purpose of /* in that context. Why not expr//f//g//h ? $\endgroup$ Nov 27, 2022 at 1:05

1 Answer 1

4
$\begingroup$

I also enjoy using "shell pipe" programming style with RightComposition. Though I prefer to use "one-columners" rather than "one-liners" because it is easy to comment. Compare

x // f/*g/*h

With

x // RightComposition[
  (* f is doing this*)
  f,
  (* g is doing that*)
  g,
  (* h wraps it up*)
  h
  ]

To answer your question, this format makes it natural to use pure functions to keep track of intermediate results and closures to use them . Here for instance, the intermediate result of f ("interf") is used in the function h.

x // RightComposition[
  (* f is doing this *)
  f,
  (* we keep the intermediary result of f*)
  interf |-> interf // RightComposition[
     (* g is doing that *)
     g,
     (* h wraps it up *)
     OperatorApplied[h,{1,2}][interf]
     ]
  ]

which give h[f[x], g[f[x]]]. OperatorApplied is flexible. For instance, if the (usually built-in) function h requires that you must compute h[g[f[x]],f[x]], Simply use OperatorApplied[h,{2,1}][interf] instead of OperatorApplied[h,{1,2}][interf]

I have never used so far this pattern on time or memory sensitive computations, but I would suppose that a functional language like the Wolfram Language would handle it efficiently.

$\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.