A puzzle with Compile

Skip to first unread message

Leonid Shifrin

Jun 6, 2009, 3:45:55 AM6/6/09
Hi everyone,

I stumbled upon a strange behavior for which I have no good explanation.

Consider the following perverse way to imitate Range:

In[1] = Module[{i = 0}, Function[x, Table[x, {10}], HoldAll][++i]]

Out[1] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

Now I attempt to speed it up with Compile:

In[2] = Compile[{{n, _Integer}},
Module[{i = 0}, Function[x, Table[x, {n}], HoldAll][++i]]][10]

Out[2] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}

Now, I am not a Compile expert, but to me it looks like it does not respect
the Hold
attribute I have given to the Function inside (this can also be confirmed by
using something
like (Print[i];++i) instead of (++i)) - printing occurs just once. Note by
the way that Table
is not a culprit either - it is HoldAll, and we may use explicit list in its
place and get the
same results.

In[3] = Module[{i = 0}, Function[x, {x, x, x, x, x}, HoldAll][++i]]

Out[3] = {1, 2, 3, 4, 5}

In[4] = Compile[{{n, _Integer}},
Module[{i = 0}, Function[x, {x, x, x, x, x}, HoldAll][++i]]][1]

Out[4] = {1, 1, 1, 1, 1}

where in this case the <n> dependence is at all spurious, and the whole
is known at compile-time (unlike the previous one where the length of the
list was
a parameter to the function). It looks like Compile's treatment of this
kind of
code is not consistent with the general principles of Mathematica evaluation
attributes mechanics.

Note that it is not like Compile can not handle held arguments at all:

In[5] = Compile[{{n, _Integer}}, Module[{i = 0}, Table[++i, {n}]]][5]

Out[5] = {1, 2, 3, 4, 5}

in which case ++i is held by Table. We can go even further:

In[6] = Module[{i = 0}, {++i, ++i, ++i}]

Out[6]= {1, 2, 3}

In[7] = Compile[{{n, _Integer}}, Module[{i = 0}, {++i, ++i, ++i}]][5]

Out[7] = {3, 3, 3}

where again, in the last example, there is no real n-dependence.

My own guess is that this sort of problems occur when Hold attributes are
used to make
a function act like a macro in some sense - that is, when effectively some
expansion must happen (to get correct results) before the code is executed
(like the above examples). But the In[5] example, which is treated
correctly, is
different only in Table being a built-in rather than user-defined, with
HoldAll also,
so I am still puzzled. Besides, for the very last example I have no
explanation whatsoever -
this one just looks like a plain bug.

Anyone having better ideas / explanation?


Reply all
Reply to author
0 new messages