32
$\begingroup$

All the cool kids are apparently using

##&[]

for

Unevaluated @ Sequence[]

but I have no idea what either means.

Please explain what these things are so I can be a cool kid!

$\endgroup$
16
  • 1
    $\begingroup$ vanishing function $\endgroup$
    – Kuba
    Apr 2, 2015 at 20:13
  • 4
    $\begingroup$ @Kuba: It takes practice. $\endgroup$
    – orome
    Apr 2, 2015 at 20:15
  • 1
    $\begingroup$ @Kuba: For reference, this is helpful too. $\endgroup$
    – orome
    Apr 2, 2015 at 20:23
  • 2
    $\begingroup$ Am I the only one who saw this in the "hot network questions" and wondered at first what the (%*# mathematica to do with *$&%ing grawlixes? $\endgroup$
    – neminem
    Apr 2, 2015 at 23:41
  • 5
    $\begingroup$ I am not extemely keen on ##&[]. It is concise (and I think clear enough after one understands it), but Function invocation is not the fastest operation in Mathematica. In most cases (except where the subtle differences actually matter), I would prefer Unevaluated@Sequence[] for explicitness and avoiding an unnecessary function call. Simon Woods's suggestion of Unevaluated[] could be the best compromise. $\endgroup$ Apr 3, 2015 at 14:37

2 Answers 2

23
$\begingroup$

Try this:

Map[If[#==1,Unevaluated@Sequence[],#]&,{1,2,3}]

Note the output. The 1 is gone. That's because Unevaluated@Sequence[] puts the empty sequence there, that is, "nothing".

##&[] is a shorthand that can be used in most places for same - ## is the sequence of arguments, & makes it a function to apply to something, [] is that something - an empty argument list, so the result is... a sequence that is empty.

$\endgroup$
7
  • $\begingroup$ This is great. I think this is what I was looking for (in a question that actually almost answers this one, and is a dupe of the one @Kuba mentions above — failing memory!) years ago: something to put in If or Which when I wanted "nothing". $\endgroup$
    – orome
    Apr 2, 2015 at 20:35
  • 4
    $\begingroup$ Good explanation. I prefer Unevaluated[] to Unevaluated@Sequence[] though I can see why the latter might be considered clearer. $\endgroup$ Apr 2, 2015 at 21:19
  • 1
    $\begingroup$ So the bottom line is that all these 3 do the same thing: Map[If[# == 1, Unevaluated@Sequence[], #] &, {1, 2, 3}]; If[# == 1, Unevaluated@Sequence[], #] & /@ {1, 2, 3}; If[# == 1, ## &[], #] & /@ {1, 2, 3}; so use the last one above. It is not only shorter than all the others, but also makes you look much smarter as well. $\endgroup$
    – Nasser
    Apr 2, 2015 at 21:48
  • 1
    $\begingroup$ @Nasser: Yeah If[# == 1, ## &[], #] & /@ {1, 2, 3}; — I mean, obviously! $\endgroup$
    – orome
    Apr 2, 2015 at 21:52
  • 3
    $\begingroup$ @raxacoricofallapatorius you can also write If[# == 1, Sequence @@ {}, #] & /@ {1, 2, 3} which gives {2, 3} also. but from now on, I will use ##&[] to be more cool. $\endgroup$
    – Nasser
    Apr 3, 2015 at 1:24
8
$\begingroup$

I believe it is important to get a fundamental understanding of what Pure Functions are that goes beyond the understanding using of a syntax. Hereafter an non-exhaustif summary of a few key understandings:

1) Pure Functions have they roots in Lambda calculus that forms the basis of functional programming paradigm implemented in Mathematica.

2) In Mathematica a Pure Function is simply an expression with the head Function that is applied to arguments.

3) Syntactially # represent a slot for arguments, whereas ## represent a sequence of arguments

4) Syntactially & represents an operator for declaring an expression as a Pure Function

5) Pure Functions have no names and therefore do not create any global defintion in Mathematica (in Lambda calculus also called anonymos functions)

6) Pure Function can be used within other expressions.

Example to point 2)

 Head[# &]
(* Function *) 

Applying a Pure Function to an argument

 Sqrt @ # &[4]
(*2*)

this is equivalent to writing

Function[x,Sqrt @ x][4]
(*2*)

Example to point 3) difference between supplying the first argument or a sequence of arguments

Plus@# &[1, 2, 3]
(*1*) 
Plus@## &[1, 2, 3]
(*6*)

PS:easy or not? even penguins would understand this..hi,hi

Unevaluted simply holds evaluation of an expression within an argument. Rasher's example demonstrates this well.

Regarding your comment, the difference between ##&[] and Unevaluated @ Sequence[] in the example from Rasher is that

a) ##&[] is short notation for Function[SlotSequence[1]][], which is evaluated to Sequence[], which then is spliced into the result {2,3}.

whereas

b) the kernel evaluates Unevaluated @ Sequence[] to Sequence[] after the function If[] has been evaluated, which is then spliced into the final result {2,3}.

Therefore due to the sequence of the evaluation process ##&[] is Unevaluated@Sequene[] and not Sequence[].

Using Trace and FullForm are powerful "tools" if you would like to go "playing in the league of cool kids". They reveal how short notation is re-written and give insight into the evaluation process.

I would recommend to compare output of following in order to get better insight:

Trace[If[# == 1, ## &[], #] & /@ {1, 2, 3}]  // FullForm

Trace[If[# == 1, Unevaluated @ Sequence[], #] & /@ {1, 2,3}] // FullForm 
$\endgroup$
3
  • $\begingroup$ This penguin doesn't understand the last bit, about Unevaluated: ## &[1, 2 + 2, 3] is Sequence[1, 4, 3], so 2+2 got evaluated, right? If so, how is ## &[] Unevaluated@Sequence[] and not Sequence[]? $\endgroup$
    – orome
    Apr 3, 2015 at 1:18
  • $\begingroup$ @ raxacoricofallapatorius, following your comment I have extended my answer. However the short answer is that It is because of the sequence of the evaluation process that ##&[] is Unevaluated@Sequene[] and not Sequence[] $\endgroup$
    – penguin77
    Apr 3, 2015 at 19:10
  • $\begingroup$ @ raxacoricofallapatorius, I made small corrections for better understanding.....vote for penguins... $\endgroup$
    – penguin77
    Apr 4, 2015 at 9:02

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