2
$\begingroup$

Consider, in the examples below, the difference between defining $n$ as a global variable or as an argument to function comp[], which includes a compiled function that depends on a constant defined in an encompassing With[] which depends on $n$.

  1. If I evaluate
ClearAll[comp, n]

n = 3;

comp = With[{x = n^2},
   Compile[{}, x]];

then running comp[] outputs 9. This is fine.

  1. If I evaluate
ClearAll[comp, n]

comp = With[{x = n^2},
   Compile[{{n, _Integer}}, x]];

then running comp[3] outputs 9. This is fine.

  1. If I evaluate
ClearAll[comp, n]

n = 3;

comp = With[{x = Array[#^2 &, n]},
   Compile[{}, x]];

then running comp[] gives me {1,4,9}. This is fine.

  1. However, if I evaluate
ClearAll[comp, n]

comp = With[{x = Array[#^2 &, n]},
   Compile[{{n, _Integer}}, x]];

I get the error "Array: Single or list of non-negative machine-sized integers expected at position 2 of Array[#1^2&,n]". The output to comp[3] is still {1,4,9} (however, in more complicated forms of example 4, the output is not what it should be).

Example 1 is to example 3 as example 2 is to example 4.

Why do examples 1-3 not give an error but example 4 does?

$\endgroup$

3 Answers 3

4
$\begingroup$

The error is thrown by Array, not by compile. With has to evaluate the code for x first and this is why Array throws the error.

$\endgroup$
6
  • $\begingroup$ Compile[] is an important part though, is it not? For example, no error is thrown in either f[n_] := With[{x = Array[#^2 &, n]}, 2] or f = With[{x = Array[#^2 &, n]}, Function[n, 2]] (f[3], for example, throws no error). If you mean the error is "Array:..." then I agree; I mentioned this in my question. $\endgroup$ Aug 7, 2020 at 16:13
  • $\begingroup$ f = With[{x = Array[#^2 &, n]}, Function[n, 2]] does throw the same error if n is undefined. $\endgroup$ Aug 7, 2020 at 16:53
  • $\begingroup$ My bad, thank you. I forgot to clear n. $\endgroup$ Aug 7, 2020 at 17:48
  • $\begingroup$ What would be the best way to pass n as an argument to comp without throwing the error? (Essentially, I'd like to get the behavior of example 3 but define n as an argument, to comp, not as a global variable). I know I can do something like comp[n_] := With[{x = Array[#^2 &, n]}, f = Compile[{}, x]; f[]], and comp[3] gives me the right answer with no error, but introducing f is a bit sloppy. Do you believe this is best? $\endgroup$ Aug 8, 2020 at 6:47
  • $\begingroup$ Well, this error can easily be ignored. You can do comp = Quiet[With[{x = Array[#^2 &, n]}, Compile[{{n, _Integer}}, x]]];. But an easier way would be comp = Compile[{{n, _Integer}}, Array[#^2 &, n]]. Or comp = Compile[{{n, _Integer}}, Table[i^2 &, {i, 1, n}]]. $\endgroup$ Aug 8, 2020 at 7:11
4
$\begingroup$

As explained by Henrik, the problem is that Array is being evaluated before it gets inserted into Compile. The solution here is to use SetDelayed to prevent its evaluation.

comp = With[{x := Array[#^2 &, n]}, Compile[{{n, _Integer}}, x]]
$\endgroup$
1
  • $\begingroup$ This seems to work, but the function I am using suffered a massive drop in speed, probably because x is now being evaluated millions of times. $\endgroup$ Aug 10, 2020 at 9:04
4
$\begingroup$

Another way:

comp = With[{x = Unevaluated@Array[#^2 &, n]}, 
  Compile[{{n, _Integer}}, x]]

By the way, Trace or TracePrint will show the order of evaluation, when there is a question about what is happening. When the code is short, like in this case, it can clarify what is going on.

TracePrint@With[{x = Array[#^2 &, n]}, Compile[{{n, _Integer}}, x]]

It also shows the desired code is injected for x, despite the error.

$\endgroup$
1
  • $\begingroup$ I use a variation of this technique: I let body = Hold[Unevaluated[Array[#^2 &, n]]]; so that I can readily generate compiled and uncompiled versions of the same code: fCompiled = Compile[{{n, _Integer}}, #] & @@ body and fUncompiled = Function[{n}, #] & @@ body. $\endgroup$ Aug 9, 2020 at 14:11

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.