Force evaluation of the right-hand side of a local variable definition

6

1

One can do

expression = a + 1;

f[a_] := Evaluate[expression]

but how would one do something like this

expression = a + 1;

g[x_] := Module[{a,b},
  a=1;
  b=Evaluate[expression];
  x*b
 ]

so that only variable b right-hand side would be evaluated and not the whole Module. This would be useful for using long formulas generated by mathematica in own function definitions.

The solution suitable for me:

Thanks Jens for the answer, that pointed me to the right direction. The solution I was looking for and works for me is

expression = a + 1;

With[{expr=expression},
 f[x_]:=Block[{a,b},
   a = 1;
   b = expr;
   x*b
 ]
]

So using With outside of SetDelayed causes evaluation of expression as desired (Jens answer) and the naming problem (a and $a) is solved by using Block instead of Module.

user72958

Posted 2015-08-10T21:57:15.387

Reputation: 61

Welcome to Mathematica.SE! I hope you will become a regular contributor. To get started, 1) take the introductory Tour now, 2) when you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge, 3) remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign, and 4) give help too, by answering questions in your areas of expertise.

– bbgodfrey – 2015-08-10T22:01:46.960

Relevant link, though not necessarily a duplicate due to Module: Evaluation in lambda function. There may well be other duplicate Q&As, but I haven't found one yet.

– Jens – 2015-08-10T23:06:14.403

Answers

8

There are two possibilities you could be aiming for. First, I'll take your question literally and just inject expression into the Module:

expression = a + 1;
With[{expression = expression},
 g[x_] := Module[
   {a, b},
   a = 1;
   b = expression;
   x*b]]

expression = 1

(* ==> 1 *)

g[xi]

(* ==> (1 + a) xi *)

As the result after changing expression shows, the earlier value of expression has been used in the definition of the Module. This was achieved by using With just as a wrapper that introduces the current value of expression literally in the definition of g.

However, this probably doesn't do what you expected, because the symbol a still appears in the last result. You probably wanted a to be replaced by 1. This could for example be done as follows:

expression = a + 1;
With[{expression = expression /. a -> 1},
 h[x_] := Module[
   {b},
   b = expression;
   x*b]]

expression = 1

(* ==> 1 *)

h[xi]

(* ==> 2 xi *)

The reason that the definition a=1; for a local variable a inside the Module doesn't work is that Mathematica doesn't actually have local variables in the strict sense. Inside the Module, it renames a to something else (a$), but the injected expression was outside of the scope where this renaming happened. Therefore, a in expression isn't the same variable as a inside the Module. To avoid this mismatch, I do the replacement of a by 1 outside of the Module.

Jens

Posted 2015-08-10T21:57:15.387

Reputation: 93 191

1

You can use Inactivate and Activate to control the evaluation of the right-hand side.

expression = Inactivate[a + 1];

g[x_] :=
  x Activate[expression /. a -> 1];

g[2]
(* 4 *)

expression
(* a + 1 *)

Inactivate prevents the execution while Activate executes without losing the inactivated expression.

Hope this helps.

Edmund

Posted 2015-08-10T21:57:15.387

Reputation: 35 657