# Composition of functions using slots

Apolgies if this has been asked and answered, but I'm not even sure what to search for. I have two functions defined as follows:

F[n_]:=Max[Select[Divisors[n],#<=Sqrt[n]&]];
P[n_] := Select[Range[1, 1000], F[#] == n &];


I have two questions:

1. I have read the Mathematica help page on the # symbol, and I think I understand most of that. I do not, however, understand what # and & do in this specific context.

2. How can I write P[n_ ] using a single line of code? It doesn't work if I simply copy and paste the definition for F into the definition of P:

P[n_] := Select[ Range[1, 1000], Max[Select[Divisors[n],#<=Sqrt[n]&]] == n &]


Answering your second question - you don't maintain a proper nesting / variable localization. Here are two correct ways (there are more):

P[n_] :=
Select[
Range[1, 1000],
With[{m = #}, Max[Select[Divisors[m], # <= Sqrt[m] &]]] == n &
]


and

P[n_] :=
Select[Range[1, 1000],
Function[m, Max[Select[Divisors[m], # <= Sqrt[m] &]] == n]]


The reason that we had to introduce an additional symbol m is that you have a function # <= Sqrt[m] & which mixes the two local variables at different levels. When this happens, you can't solve the problem using only slot-based functions, due to the apparent collision of essentially different variables.

Perhaps, the fact that you denote the argument for your original functions as n in both cases was what led to the conclusion. As a side note, avoid starting your function names with capital letters, this may lead to collisions with system symbols.

I believe that there is already an answer for the general slot-nesting question somewhere here on SE, so this answer likely has a temporary status.

In theory you can use only slot-based functions:

P1[n_] := Select[Range[1, 1000], Max@Select[Divisors[#],
Function @@ {Identity[Slot][] <= Sqrt[#]}] == n &];

P2[n_] := Select[Range[1, 1000],
Max@Select[Divisors[#3], #1[#2[] <= Sqrt[#3]]] == n &[Function, Slot, #] &];


You can even use the slot instead of n:

P3 = Select[Range[1, 1000], #1[Max@Select[
Divisors[#3], #1[#2[] <= Sqrt[#3]]] == #4 &[#1, #2, #2[], #3]]] &[Function, Slot, #] &;

P == P1 == P2 == P3


True

Surely it is a very complicated approach, which is inappropriate for practical use. It is just an answer to Leonid's "you can't solve the problem using only slot-based functions".

• Excellent answer, thank you. I tried about a thousand different ways of using only slot-based functions, but I would never have come up with anything close to this. – Ashton Baker Nov 3 '13 at 22:57
• +1. So, you solve the collision problem by delaying the binding, constructing the inner function at runtime. I haven't thought of that, pretty clever. OTOH, my statement was concerning the most straight-forward way. If you think of it, my first method (using With) is akin yours. – Leonid Shifrin Nov 4 '13 at 0:08