Defining a function with global parameters

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.)

• 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. – azag0 Feb 21 '14 at 0: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 0:18
• Try defining g as g[aa_] := Block[{a = aa}, NIntegrate[f[x], {x, 0, 1}]]. – Alexey Popkov Feb 22 '14 at 8: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

1 Answer

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}]