# Variables Inside Functions Not Evaluating

x = 5*y
function1[y_] := x
function1[5]


Am I wrong in thinking that function1[5] should equal 25? Instead this comes out.

5y
5y

-
Use underscore _ (like y_ in your example) to define the variable of a function. – b.gatessucks Sep 12 '12 at 13:57
I suggest you to read this, and generally that chapter - this should make things clear. – Leonid Shifrin Sep 12 '12 at 13:58
sorry i had y_ in my program but i just printed it here wrong i've updated it now – Cadell Christo Sep 12 '12 at 14:06
Ok then it is a different thing. While you were given a work-around, I would advice against such uses at all - it is much better to declare all variables on which your function depends as formal parameters. Please see this answer for the reasoning. – Leonid Shifrin Sep 12 '12 at 15:15

Without going into too much detail, this is a result of the way pattern matching is carried out. When you write the rule f[y_]:={x,y} for instance, it tells the compiler that it should match anything and call it y, then replace any instance of y on the right side with the match. But x doesn't evaluate until after this has already happend. A good way to see what goes on is to use Trace

x = 5 y;
f[y_] := {x, y}
f[3] // Trace


(*=> {f[3],{x,3},{x,5 y},{5 y,3}} *)

The way to get around this is to get x to evaluate before you define the rule, which you can do for instance by passing it through an anonomous function:

(f[y_] := {#, y})&@x
f[3] // Trace
(*=>  {f[3],{5 3,3},{5 3,15},{15,3}} *)


If you want to see why this works out you can see that at the time the rule definition is evaluated x has been fully replace by using Trace on the code defining the function

 (f[y_] := {#, y}) &@x // Trace

(*=> {{x,5 y},((f[y_]:={#1,y})&)[5 y],f[y_]:={5 y,y},Null} *)

-
thank you! for your detailed answer that's exactly what I needed. I also experimented and found if I removed the semicolon on the function it worked is that bad practice? – Cadell Christo Sep 12 '12 at 14:17
@CadellChristo Of cause that also works, since it does the exact same thing, however if you have something like x=5 y; y=4;f[y_]={x,y} then you should note that the y on the right hand side of your function definition will not be replaced by the matched pattern. My posted solution is less pretty but allows you to control what is evaluated and what is kept. – jVincent Sep 12 '12 at 14:21
okay thanks for all your help. – Cadell Christo Sep 12 '12 at 14:25

What you want do is this:

function1[y_] := 5*y;


The way you define functions in Mathematica is by defining patterns, which is indicated here by y_, which matches any expression. So function1[y] is always replaced by 5 times whatever y is when evaluated. What you did is define a symbol called x, then make a delayed definition called function1[y] which equals x. But function1[5] has never been defined.

-
thanks for the reply I did make the initial error of not printing the y_ but can I not define a function with a variable in it like I have done or do i need to define it in a different way? – Cadell Christo Sep 12 '12 at 14:11

As already explained the named pattern y_ is only substituted for explicit instances of y in the right-hand side.

As a point of reference this works:

x = 5*y;
function1[y_] = x;
function1[5]

25


The value of x is hard coded into function1:

Definition[function1]

function1[y_] = 5 y


An approach that will let you change the value of x is to use Block:

function2[yy_] := Block[{y = yy}, x];

function2[5]

25

x = 7 y;

function2[5]

35

-