A puzzle with Compile

47 views
Skip to first unread message

Leonid Shifrin

unread,
Jun 6, 2009, 3:45:55 AM6/6/09
to
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
structure
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
code
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?

Regards,
Leonid


Reply all
Reply to author
Forward
0 new messages