# Difference between (#1[[2]] < #2[[2]]&) and (#1[[2]] & < #2[[2]] &) [closed]

For example, if I have a list {{a, 2}, {c, 1}, {d, 3}} and I want to sort it w.r.t. the numbers:

In[2]:= Sort[{{a, 2}, {c, 1}, {d, 3}}, #1[[2]] < #2[[2]] &]

Out[2]= {{c, 1}, {a, 2}, {d, 3}}


Why does it matter if I put an "&" right after #1[[2]]?

In[3]:= Sort[{{a, 2}, {c, 1}, {d, 3}}, #1[[2]] & < #2[[2]] &]

Out[3]= {{a, 2}, {c, 1}, {d, 3}}

• Compare with FullForm. – Kuba Nov 16 '17 at 16:33
• Also realize that these expressions are parsed as (#1[[2]] < #2[[2]]) & and ((#1[[2]]) & < #2[[2]]) & -- you can see this from their FullForm. – jjc385 Nov 16 '17 at 16:39

The & distinguishes the end of the anonymous function. As FullForm shows, the first expression is identical to:

(#1[[2]]<#2[[2]]&)===Function[Less[Part[Slot[1],2],Part[Slot[2],2]]]

(#1[[2]]<#2[[2]]&)===Function[#1[[2]] < #2[[2]]]


Whereas the second expression is actually two nested functions:

(#1[[2]]&<#2[[2]]&)===Function[Less[Function[Part[Slot[1],2]],Part[Slot[2],2]]]

(#1[[2]]&<#2[[2]]&)===Function[(Function[#1[[2]]])<#2[[2]]]


Thus, the reason that it matters is that, as written, the inner function won't receive the arguments required to do its job. If these arguments are passed it will technically work, but nesting functions needlessly like that is wasteful for most applications.

That said, this is how it could be done:

(#1[[2]]&[##] < #2[[2]]&)


[##] passes the entire argument list of the outer function into the inner function.

In the second case, you are creating two functions instead of one. Interestingly, the two functions are nested: at first glance I expected the result to be equivalent to (#1[[2]] &) < (#2[[2]] &), but it is equivalent to ((#1[[2]] &) < #2[[2]] &). As @Kuba suggested, look at the FullForm. As a result, the comparison is failing in the second case. For example, (#1[[2]] & < #2[[2]] &)[{a, 2}, {c, 1}] evaluates to #1[[2]] & < 1.