Why isn't Table iterator value inserted in failed NIntegrate arguments?

Consider this simplest example:

Table[{z, NIntegrate[f[x], {x, 0, z}]}, {z, {1}}]


Here f is not defined, so NIntegrate is expected to fail, which it does:

NIntegrate::inumr: The integrand f[x] has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1}}. >>

But what happens additionally is quite a strange error message:

NIntegrate::nlim: x = z is not a valid limit of integration. >>

When I look at the resulting table, I see

{{1, NIntegrate[f[x], {x, 0, z}]}}


So, for some reason z appears in the NIntegrate arguments not substituted by its value of 1, although it is substituted by 1 in %[[1,1]] element.

What happened? Why does the resulting expression not know the value of iterator? How do I force it to, so that the result would have {x,0,1} instead of {x,0,z}?

• The function NIntegrate has attribute HoldAll, so its arguments remain unevaluated at the function call. Wrap {x,0,z} in Evaluate (assuming that x does not have a value) to force evaluation. – Fred Simons May 11 '15 at 6:11
• @FredSimons great, this could be made an answer. – Ruslan May 11 '15 at 6:38
• I have nothing to add to the excellent answer of Mr. Wizard. – Fred Simons May 11 '15 at 10:09

As Fred Simons comments NIntegrate has the HoldAll attribute but alone that does not explain this behavior. With the literal assignment z = 1 no NIntegrate::nlim message prints:

z = 1;

NIntegrate[f[x], {x, 0, z}]


Table normally works by the same mechanism as Block, and indeed we see the same behavior from Block:

ClearAll[f, x, z]

Block[{z = 1}, NIntegrate[f[x], {x, 0, z}]]


NIntegrate::inumr: The integrand f[x] has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1}}. >>

NIntegrate::nlim: x = z is not a valid limit of integration. >>

What is happening is that the unevaluated form of the failed NIntegrate expression is returned outside that construct and re-evaluated in that environment where z has no value. To make this more explicit consider:

z = "outside Block";

Table[NIntegrate[f[x], {x, 0, z}], {z, {"inside Block"}}]


NIntegrate::nlim: x = inside Block is not a valid limit of integration. >>

NIntegrate::nlim: x = outside Block is not a valid limit of integration. >>

Attempt at clarification

For the function (e.g. NIntegerate) to return unevaluated from Table or Block it must have a hold attribute and be written such that a Condition or PatternTest fails. Understand that messages may be generated even when a condition fails; for detailed examples see my answer to How to program a F::argx message? As a simplified example for the purpose of this answer consider:

Attributes[foo] = {HoldAll};

foo[x_, y_] /; x < 5 || Print[x, " not less than five"] := x^y


This definition has a Condition which contains a Print expression (a proxy for Message for this example) -- if x is not a numeric quantity less than five a message will be printed and the condition will fail as Print returns Null, not True. Because no definition for foo matches the input is returned without further evaluation:

foo[9, 3]


9 not less than five

foo[9, 3]


If this takes place inside Block the unevaluated form is returned from Block to the global environment:

Block[{bar = 7}, foo[bar, 2]]


7 not less than five

bar not less than five

foo[bar, 2]


Note that one message is printed for the value of bar inside the Block and another is printed for the evaluation that takes place afterward where bar has no value. If bar is given a global value it will be used:

bar = 4;

Block[{bar = 7}, foo[bar, 2]]


7 not less than five

16

• Hmm, so does this mean that the unevaluated form is returned by Table as a specially handled thing, not as a result of evaluation? I.e. if we had noIntegrate[z], it'd be returned as noIntegrate["inside Block"] for undefined noIntegrate, while if noIntegrate call were to fail, it'd be returned as noIntegrate[z], right? – Ruslan May 11 '15 at 7:14
• @Ruslan only if noIntegrate is written that way. Let me think about this and attempt to add clarifying examples. – Mr.Wizard May 11 '15 at 7:15
• @Ruslan I updated the answer. I hope it is more clear now. Please let me know. – Mr.Wizard May 11 '15 at 7:34
• Great, this makes it clear, thanks. – Ruslan May 11 '15 at 7:39