19
$\begingroup$

Consider

AbsoluteTiming[Range[10^7];][[1]]

0.035000

and

AbsoluteTiming[HoldComplete @@ Range[10^7];][[1]]

0.725000

Why it takes twenty times longer to change head than to create a list? Since HoldComplete doesn't evaluate arguments one would think that head changing should be fast.

$\endgroup$
3
  • 7
    $\begingroup$ Because HoldComplete unpacks, when Apply is used (or, rather, Apply unpacks). $\endgroup$ May 25, 2013 at 11:14
  • $\begingroup$ @Leonid Shifrin no preamble, but clearly answer material. $\endgroup$
    – Yves Klett
    May 25, 2013 at 16:10
  • $\begingroup$ @YvesKlett All right, I followed your suggestion. $\endgroup$ May 25, 2013 at 17:26

1 Answer 1

17
$\begingroup$

In your example, you originally create a packed array. If you read about packed arrays in the answers in the linked question, in documentation or elsewhere, you will see that these are special objects, lower-level than general Mathematica lists / expressions.

Because of this, not all Mathematica operations preserve these objects. Those which don't are said to unpack. Some considerations regarding (avoiding) unpacking can be found here. In particular, it was mentioned and illustrated there that Apply necessarily unpacks. This is just because of its nature: it replaces the current head of an expression with a different head.

It is easy to check whether or not unpacking happens - use On["Packing"]:

On["Packing"]

HoldComplete @@ Range[10]

During evaluation of In[125]:= Developer`FromPackedArray::punpack1: Unpacking array with dimensions {10}. >>

(*  HoldComplete[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  *)

Off["Packing"]

Unpacking is a process of replacing a packed array with its unpacked, higher-level equivalent generic Mathematica list. For large arrays, this can take quite some time, which is what you observed. This has nothing to do with HoldComplete, because unpacking happens slightly earlier, and has nothing to do directly with the top-level evaluation - which is the only evaluation that HoldComplete may affect. Unpacking is a lower-level action.

$\endgroup$
9
  • 3
    $\begingroup$ Setting the 0th Part to something other than List also unpacks. So, although it's true that Apply does unpack, I think the reason is that packed arrays can only have head List, rather than that this is due to Apply itself. $\endgroup$ May 25, 2013 at 19:26
  • $\begingroup$ @OleksandrR. Sure, I implied this. Perhaps, I could have articulated this point better, thanks. $\endgroup$ May 25, 2013 at 20:00
  • $\begingroup$ @LeonidShifrin - I remember reading in the docs that Range[] had some sort of special internal representation, but don't recall it was ever explained beyond that. Makes me wonder about how best to use this function (so as to avoid the problem OP stumbled into). Interesting. $\endgroup$ May 30, 2013 at 4:47
  • $\begingroup$ @telefunkenvf14 It's not just about Range - all packed arrays are like that. You can think of them as an internal (lower-level) data type on which all relevant Mathematica's built-in functions have been overloaded. Some of the suggestions how to use them effectively you can find in the links I gave in the answer. $\endgroup$ May 30, 2013 at 10:29
  • 1
    $\begingroup$ I appreciate the edit, but to "crate a packed array" sounded quite appropriate. :) $\endgroup$
    – Michael E2
    Nov 12, 2015 at 0:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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