1

What I would like to do in Mathematica is something like

f[x_] := a x
g[a_] := NIntegrate[f[x], {x, 0, 1}]

But then of course I get

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

But I found that I can circumvent the problem with

g[a_] := Hold[NIntegrate][f[x], {x, 0, 1}] // Evaluate // ReleaseHold // Evaluate
    NIntegrate::inumr: The integrand a x has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1}}. >>
g[1]
Out= 0.5

I don't really understand why this works nor why the definition of g throws an error. As I haven't found any other solution to my problem, I would really like to understand why my "solution" works which should also provide an answer to whether there is a simpler solution.

(I understand I can solve this simple problem with f[x_, a_] but I have in fact a more complex environment in hand where this approach becomes inconvenient.)

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
jhrmnn
  • 265
  • 1
  • 8
  • It becomes inconvenient because I have more oen parameters and later define other functions based on f which I then use in different combinations. So I would have to type expressions like g[x,a,b,c]h[g[x,a,b,c],a,b,c] instead of much clearer g[x]h[g[x]]. This wouldn't matter if I was creating static code, but I am in fact prototyping and trying different combinations all the time. –  Feb 21 '14 at 00:16
  • OK, but you still didn't explain why my suggestion wouldn't work, i.e. encapsulate those parameters into the function at the beginning. – Szabolcs Feb 21 '14 at 00:18
  • Try defining g as g[aa_] := Block[{a = aa}, NIntegrate[f[x], {x, 0, 1}]]. – Alexey Popkov Feb 22 '14 at 08:13
  • @Nasser Because later I might want to do something like (f[x]^2 Sin[f[x]]+Cos[f[x]]/.a->1)+(f[x]^3 Cos[f[x]]+Sin[f[x]]/.a->2). Now I can of course do that easily with f[x,a], but it will be much more typing and during prototyping and with more parameters, it quickly becomes very time-consuming. – jhrmnn Feb 25 '14 at 12:35
  • @AlexeyPopkov This works nicely, thanks! Now the original question remains unanswered, but I don't need the answer anymore and I'm not sure whether the question is worthy in general? – jhrmnn Feb 25 '14 at 12:42
  • @azag0 I have added an answer so you can accept it. I also renamed the question to make it more clear. – Alexey Popkov Feb 25 '14 at 16:40

1 Answers1

1

One workaround is to define g as:

g[aa_] := Block[{a = aa}, NIntegrate[f[x], {x, 0, 1}]]

This works because f[x] now is evaluated in local environment where variable a has a value.

The reason why the version

g[a_] :=  NIntegrate[f[x], {x, 0, 1}]

does not work is that a is absent on the right side of the definition, so nothing will be replaced: SetDelayed (:=) creates a RuleDelayed replacement rule which performs lexical scoping. So evaluating for example g[1] is equivalent to evaluation of g[a] or any other such construct.


Your "solution" is essentially equivalent to

g[a_] = NIntegrate[Evaluate@f[x], {x, 0, 1}]

In both cases the real replacement rule generated contains the variable a on the right hand side:

?g
g[a_]=NIntegrate[a x,{x,0,1}]
Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368