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