18
$\begingroup$

Here is the example, copied from here

square = Function[x, x^2];
square1 = #^2 &;

the timing and unpacking status shows

data = RandomReal[{0, 10}, {10000}];

AbsoluteTiming[Developer`PackedArrayQ[Map[square, data]]]
AbsoluteTiming[Developer`PackedArrayQ[tmp1 = Map[square1, data]]]

{0.000771589, True}
{0.000748647, True}

Now we add external variable into these two definition.

a = 1
square = Function[x, x^2 + a];
square1 = #^2 + a &;

and time it again, you got

{0.0336384, False}
{0.0062035, True}

we can see & is still autocompiled, while Function is not. Why? I think the documentation treats them as identical way of writing. This distinction is oddly subtle, I just found it today. What is bad is that without Function, we can not give parameters names, thus less readability.

$\endgroup$
10
  • $\begingroup$ To be precise, it seems that square = Function[x, x^2 + a]; isn't compared in Map. I think this can be considered as another evidence that the auto-compilation of pure function is still not that stable currently. $\endgroup$
    – xzczd
    Dec 3, 2016 at 6:27
  • 1
    $\begingroup$ It's not just about autocompilation. square is slower than square1 without compilation. You can use Trace to see that there is a significant difference in the evaluation. Autocompilation can be switched of with SetSystemOptions["CompileOptions" -> {"MapCompileLength" -> \[Infinity]}] and increases the difference in your second case, while it removes the difference in your first case. $\endgroup$
    – Karsten7
    Dec 3, 2016 at 7:22
  • $\begingroup$ Hi, @Karsten7. I think it is might not be the point. The goal to use Function is to make use of autocompilation. When & and Function both been autocompiled, they are of same speed. If speed is not of concern, then I can just use square2[x_] := x^2;, and in case of "MapCompileLength" -> \[Infinity], square2[x_] := x^2 is actually faster than Function. $\endgroup$
    – matheorem
    Dec 3, 2016 at 7:47
  • 3
    $\begingroup$ square2 = With[{a = a}, Function[x, x^2 + a]] would autocompile properly. Maybe "InlineExternalDefinitions" is handled differently? $\endgroup$
    – Karsten7
    Dec 3, 2016 at 7:50
  • 3
    $\begingroup$ SetSystemOptions[ "CompileOptions" -> {"CompileReportFailure" -> True, "InternalCompileMessages" -> True}] can be used to switch on the generation of an error message. $\endgroup$
    – Karsten7
    Dec 3, 2016 at 7:51

1 Answer 1

8
$\begingroup$

The solution, as suggested by Karsten7, in a comment is to use With.

data = RandomReal[{0, 10}, {10000}];

a = 1;
With[{a = a}, square = Function[x, x^2 + a]];
square1 = #^2 + a &

Timing[Developer`PackedArrayQ[Map[square, data]]]
Timing[Developer`PackedArrayQ[tmp1 = Map[square1, data]]]

{0.000578, True}

{0.000528, True}

$\endgroup$
1
  • 1
    $\begingroup$ The question asks why, perhaps we could elucidate the underlying reason. $\endgroup$
    – M.R.
    Jan 10, 2017 at 3:07

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.