I've seen people compare Block with Module and With as scoping constructs, and try to figure out when to choose which. Also, I've seen posts about Function versus # versus downvalue functions.
However, I already understood the differences between those, but still find myself more often doubting between functions and With...
Does With have any advantage in any case over Function?
I am talking about this constructions
With[{sth=inj}, code code sth code]
versus
(code code # code)&[inj]
or
Function[sth, code code sth code][inj]
Apart from the fact that its syntax is better suited for defining constants since the variable name and value are "together", or other elegance issues I mean.
They are both scoping constructs, and Function among other uses can also inject code as With. If With's variables are set with := you can always use Function version with attributes.
I know, this doesn't hold in the infrequent situation when you would use a With with, e.g, 2 :=s and 2 =s which can't be emulated by a function attribute.
In the (not so extensive) tests I've done it doesn't seem to be faster.
In[127]:= TimingAverage[
With[{sum = 2 + 8},
{sum*x, sum*y}]]
Out[127]= 3.42178*10^-6
In[124]:= TimingAverage[
Function[{sum}, {sum*x, sum*y}][2 + 8]
]
Out[124]= 3.36266*10^-6
In[122]:= Module[{lalala},
lalala[sum_] := {sum*x, sum*y};
TimingAverage[
lalala[2 + 8]
]
]
Out[122]= 2.88582*10^-6
In[123]:= TimingAverage[
{#*x, #*y} &[2 + 8]
]
Out[123]= 2.67792*10^-6
Just out of curiosity, this very same test seem to be consistent with the common knowledge of Module being slower than Block being slower than With
In[119]:= TimingAverage[
Module[{sum = 2 + 8},
{sum*x, sum*y}]]
Out[119]= 7.19833*10^-6
In[120]:= TimingAverage[
Block[{sum = 2 + 8},
{sum*x, sum*y}]]
Out[120]= 4.58145*10^-6
As to the holding version of the tests, we get marginally better results with With
In[129]:= TimingAverage[
Function[{sum}, {sum*x, sum*y}, HoldFirst][2 + 8]
]
Out[129]= 4.22668*10^-6
In[128]:= TimingAverage[
With[{sum := 2 + 8},
{sum*x, sum*y}]]
Out[128]= 3.8681*10^-6
In[131]:= Module[{lalala},
SetAttributes[lalala, HoldFirst];
lalala[sum_] := {sum*x, sum*y};
TimingAverage[
lalala[2 + 8]
]
]
Out[131]= 3.45039*10^-6
EDIT
As to style and elegance, I guess that functions are more suited when the expressions you're injected are big and the code you're injecting them into is small, and With otherwise.
Any thoughts on all this issue? Am I missing something?
With[{x=1,n=2}, x^n]vsFunction[{x,n}, x^n][1,2]. InFunctionthe "constants" (i.e.xandn) are named at the beginning, at set at the end without their name being mentioned. This is a significant usability disadvantage when you just want to put inject a number of expressions into code. Otherwise I think there's no behavioural difference between them for the use you mention. – Szabolcs Jan 26 '12 at 09:57