5
$\begingroup$

Is it possible to construct a pure function using multiple slots, with the following concept :

      Binding   specific slot    to    specific apply or map

For example :

enter image description here

In this example,

To reproduce the output for In(1), namely Out(1),

In[1] Table[Take[#, n], {n, 1, Length[#]}] & /@ test
Out[1] {{{4}, {4, 2}, {4, 2, 2}}, {{9}, {9, 1}, {9, 1, 5}}, 
       {{5}, {5, 2}, {5, 2, 9}, {5, 2, 9, 3}}, 
       {{5}, {5, 2}, {5, 2, 7}, {5, 2, 7, 1}, {5, 2, 7, 1, 1}}}

without using 'Table' symbol, I could do

In[2] Function[x, (Function[y, Take[x, y]] /@ Range[Length[x]])] /@ test

But I want to reproduce Out(1), only with slot symbols and Map.

The codes

((Take[#1, #2] &) /@ Range[Length[#1]]) & /@ test

or

((Take[#, #] &) /@ Range[Length[#]]) & /@ test

are tryable but they fails.

My imaginary working colored code is like :

enter image description here

Violet # binds to violet & and violet /@,
Green # binds to green & and green /@

$\endgroup$
7
  • 2
    $\begingroup$ What about: Function[x, Take[x, #] & /@ Range[Length[x]]] /@ test $\endgroup$ Apr 1, 2021 at 15:46
  • 1
    $\begingroup$ Try e.g.: FoldList[Append, {First@#}, Rest@#] & /@ test or i f you are a fan of cryptic code: (t = #; Take[t, #] & /@ Range[Length[#]]) & /@ test $\endgroup$ Apr 1, 2021 at 16:30
  • 2
    $\begingroup$ It's worth noting, by the way, that & with # is simply shorthand for Function with a parameter, so the Function solution is actually how you would bind a slot (in this case, named x) in an anonymous function properly. $\endgroup$
    – thorimur
    Apr 1, 2021 at 17:20
  • 3
    $\begingroup$ You cannot bind a Slot to a Function constructor & outside another constructor & ("outside" being defined by syntactic precedence). As far as I know, at least. This came up before, but as I recall, it was not the central question, just the explanation of the problem with the OP's code. $\endgroup$
    – Michael E2
    Apr 1, 2021 at 20:02
  • 1
    $\begingroup$ Another way to look at it is that Slot[] binds to the first Function going up the expression tree to the head. To visualize your last example: (Take[#1, #1] &) /@ Range[Length[#1]] & // TreeForm The first Slot[1] in Take[..] won't bind to the topmost Function as desired. You would need a way to label the slots and the function, but such a way is already provided by symbolic arguments. $\endgroup$
    – Michael E2
    Apr 1, 2021 at 20:11

2 Answers 2

3
$\begingroup$

There is no direct notation for anonymous slot references to outer pure function arguments (named arguments to Function having been ruled out). But we can use the higher-order function OperatorApplied as a way to avoid explicit argument naming:

OperatorApplied[Take, 2][#] /@ Range@Length[#] & /@ test

(* {{{4}, {4,2}, {4,2,2}},
    {{9}, {9,1}, {9,1,5}},
    {{5}, {5,2}, {5,2,9}, {5,2,9,3}},
    {{5}, {5,2}, {5,2,7}, {5,2,7,1}, {5,2,7,1,1}}} *)

or, equivalently:

OperatorApplied[Take[#2, #]&][#] /@ Range@Length[#] & /@ test

For this particular case, CurryApplied could be substituted for OperatorApplied. We could also use Curry (my old favourite) but it has been deprecated and slated for removal some day.

See (197168) for more discussion of this currying technique within nested pure functions.


Just For Fun

If Wolfram Language had some kind of forking operator, we could dispense with slot notation for this example and write in point-free form:

fork[f_][g_, h_][x_] = f[g[x], h[x]]

test // Map@fork[Map][Curry[Take,2], Range@*Length]

(* {{{4}, {4,2}, {4,2,2}},
    {{9}, {9,1}, {9,1,5}},
    {{5}, {5,2}, {5,2,9}, {5,2,9,3}},
    {{5}, {5,2}, {5,2,7}, {5,2,7,1}, {5,2,7,1,1}}} *)

The Query sublanguage has something resembling a fork operator, so we can write:

test // Query[All, Apply[Map]@*{Curry[Take, 2], Range@*Length}]
$\endgroup$
1
  • $\begingroup$ I'm really going to miss Curry. I dislike long names like OperatorApplied or CurryApplied for common (at least for me) operations. $\endgroup$
    – WReach
    Apr 2, 2021 at 13:34
7
$\begingroup$

You can do it even without slots:

Map[Map[Flatten @* List] @* FoldList[List]] @ test  
 {{{4}, {4, 2}, {4, 2, 2}}, 
  {{9}, {9, 1}, {9, 1, 5}}, 
  {{5}, {5, 2}, {5,  2, 9}, {5, 2, 9, 3}}, 
  {{5}, {5, 2}, {5, 2, 7}, {5, 2, 7, 1}, {5, 2, 7, 1, 1}}}

Also

Map[Extract[#, Map[List] @ Range @ Range @ Length @ #] &] @ test  
 {{{4}, {4, 2}, {4, 2, 2}}, 
  {{9}, {9, 1}, {9, 1, 5}}, 
  {{5}, {5, 2}, {5,  2, 9}, {5, 2, 9, 3}}, 
  {{5}, {5, 2}, {5, 2, 7}, {5, 2, 7, 1}, {5, 2, 7, 1, 1}}}
$\endgroup$

Your Answer

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

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