Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I've moved this question over from StackExchange to get better visibility (and deleted the old question).

I have a user-defined relationship I'd like to plot:

a = (b + c)/d;

and I try to plot it as follows:

plotFunction[b_, c_] := Plot[a, {d, 0, 10}];
plotFunction[2, 3]

This results in an empty plot; only the axes are drawn. Of course the following works fine:

plotFunction[b_, c_]:= Plot[(b + c)/d, {d, 0, 10}];
plotFunction[2, 3]

I don't understand why MMA refuses to draw the function in the first method? I've tried using Show[] as well; no luck. I even tried passing the relationship within the function as follow - no luck:

plotFunction[a_, b_, c_]:= Plot[a, {d, 0, 10}];
plotFunction[a, 2, 3]

I suppose it could have something to do with local vs global variable definitions inside and outside the function definitions?

share|improve this question
2  
Define a[b_,c_,d_] = (b + c)/d and use accordingly in Plot[]. –  b.gatessucks Apr 10 '12 at 14:45

4 Answers 4

My interpretation is that your main issue was simply a misunderstanding of what the arguments b_, c_ etc mean in the definition of your plots. The underscore _ marks them as "dummy variables" or "stand-ins" for the actual values passed to your plotFunction. That makes them completely independent of the variables named b and c on which your initial definition

a = (b + c)/d

relies. So if we start from the premise that you want to keep using this definition, then it would be less confusing to use different names for the "dummy variables" in PlotFunction. Not only less confusing, but also more useful, as we can already see in the answer by celtschk.

So I'll rename the function's dummy variables bDummy and cDummy, but then I have to tell the evaluator (i.e., the eager voice in tkott's narrative) what to do with these once we've been given actual values for them. Instead of defining a Block, you can do this as follows:

plotFunction[bDummy_, cDummy_] := 
       Plot[a /. {b -> bDummy, c -> cDummy}, {d, 0, 10}]

This uses a replacement rule: /. means ReplaceAll (see the Documentation) and is followed by a list of rules like b -> bDummy which now instruct Mathematica to replace the variable (symbol) b by the value of bDummy at the time the function is called (and similarly for c).

It is quite important to know how one can define functions that interact with globally defined objects in addition to their "dummy variables", and replacement rules are a very common way of doing this. Basically, in this example they are used to "inject" the current values of the function argument into a previously defined expression.

share|improve this answer

In addition to the solutions already posted, here's one you can use if you don't want to change the definition of a (e.g. because you've already used it a lot):

plotFunction[bb_,cc_]:=Block[{b=bb,c=cc},Plot[a,{d,0,10}]]

Now when you do

plotFunction[2,3]

the initial replacement will result in Block[{b=2,c=3},Plot[a,{d,0,10}]]. The Block construct temporarily binds the values of b and c, as can be seen by typing

Block[{b=2,c=3},{OwnValues[b],OwnValues[c]}]
(*
==> {{HoldPattern[b] :> 2}, {HoldPattern[c] :> 3}}
*)

Now the Plot will bind d to different values between 0 and 10 (it is really the global value of d which is changed, as can be seen by evaluating Dynamic[d] before starting the Plot command), and for each value of d evaluate a. Evaluation of a will first give the expression (b+c)/d, and since at this point there are OwnValue bindings for b and c (through Block) and d (through Plot), those are used to further evaluate this expression to (assuming e.g. d currently is 2.5) (2+3)/2.5 which then evaluates to 2. and gives the point {2.5,2.} for the plot.

share|improve this answer

It's important to realize that when setting something up of the type:

f[x_]:=x

That you are setting a replacement rule, not creating a function. See Functions vs. patterns for a further discussion of this.

In the current situation, what you wrote has the following effect. First, you define:

plotFunction[b_, c_] := Plot[a, {d, 0, 10}];

when you call

plotFunction[2, 3]

MMA does something like the following. "Oooh, I found a pattern that matches plotFunction[b_, c_], I need to replace it, and then evaluate it!" Replacing it makes the right hand side look like:

Plot[a, {d, 0, 10}]

Since there wasn't anything for b and c to replace, the above is what MMA will now evaluate. Evaluating the expression, it says "Ooooh, oooh, I know how to deal with a!", so it replaces it:

Plot[(b + c)/d, {d, 0, 10}]

Then it tries to actually call the replacement-rule ("built-in-function") Plot which fails, since b and c are not numbers, as you saw. However, if you define:

a[b_,c_,d_]=(b + c)/d    
plotFunction[b_, c_] := Plot[a[b, c, d], {d, 0, 10}];

And call:

plotFunction[2, 3]

MMA first replaces plotFunction with:

Plot[a[2, 3, d], {d, 0, 10}]

Then evaluates that, at which point it sees that there is another pattern it knows how to deal with (a[b_,c_,d_]=(b + c)/d) and replaces that:

Plot[(2 + 3)/d, {d, 0, 10}]

And only then plots it, which results in the correct plot.

For dealing with these types of replacement problems, I strongly suggest the use of WReach's traceView functions. For Plots, this doesn't always help, but can be instructive.

share|improve this answer
    
I never imagined mma could be so eager and dramatic, but kudos for the imagery :) –  rm -rf Apr 10 '12 at 18:21
    
@R.M See also xkcd.com/869 –  tkott Apr 10 '12 at 18:32
a[b_, c_] := (b + c)/d;
Plot[a[5, 3], {d, 0, 10}]

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.