1
$\begingroup$

This question already has an answer here:

For example, I have

eq1=ax+by+cz;

and then I want to define new function, $eq2$, as

eq2[x_]:=Coefficient[eq1,a];

eq2 supposed to be function of x and in this case

eq2[x]=x;

However, eq2 is "actually" equal x. I mean it doesn't matter which x I put to the argument of eq2, I always get "x". For example, eq2[1]=x, eq2[2]=x.

How could I define the eq2 and make it really a function of x?

Thanks.

$\endgroup$

marked as duplicate by Michael E2, Feyre, corey979, Community Oct 30 '16 at 9:14

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ eq2[x_] := Evaluate@Coefficient[eq1, a] $\endgroup$ – corey979 Oct 29 '16 at 8:38
  • $\begingroup$ @corey979 I have tried your suggestion and it's work. $\endgroup$ – Natthawin Cho Oct 29 '16 at 13:38
  • $\begingroup$ @MichaelE2 I have read that question after you mentioned it. However, I don't think it's duplicate. In my case, I already used SetDelayed, so the result seem to depends on x but it's not. Do you have any comments about my problem if it is duplicate? $\endgroup$ – Natthawin Cho Oct 29 '16 at 13:40
  • $\begingroup$ Does eq2[x_] = Coefficient[eq1,a]; work? (I.e., use Set instead of SetDelayed. Set is more or less equivalent to corey's use of SetDelayed and Evaluate.) $\endgroup$ – Michael E2 Oct 29 '16 at 13:47
  • $\begingroup$ @MichaelE2 yes it works. Do you have explanation? I have tried to find the explanation from the question you mentioned but I "think" I can't find because if I use Set, it seem to be set eq2 at that value and not depends on changing of x in the future. $\endgroup$ – Natthawin Cho Oct 29 '16 at 13:53
2
$\begingroup$

It's a question of What is the difference between Set and SetDelayed? The issue is also discussed in the tutorial Immediate and Delayed Definitions; more can be found in Leonid's book. A subtle difference between Set and SetDelayed is discussed in Does Set vs. SetDelayed have any effect after the definition was done?

Let's think of the OP's code and its alternative

eq2[x_] := Coefficient[eq1,a];
eq2[x_] = Coefficient[eq1,a];

in more general terms as the alternatives

f[x_] := expression;
f[x_] = expression;

The first, SetDelayed definition creates a rule so that the code f[x0] results in the literal occurrences of x in expression to be replaced by x0 and then the resulting expression is evaluated. In the OP's case, the expression is Coefficient[eq1,a], which literally contains no x. By "literal," I mean that the symbol x has to occur in the unevaluated code. The symbol eq1 is literally just a symbol. Only after it is evaluated, does one obtain the expression a x + b y + c z that contains x. That brings us to the difference with Set.

The second, Set definition creates a rule so that the code f[x0] results in the literal occurrences of x in the evaluated expression to be replaced by x0. Note I said that expression is evaluated before the rule is created. In the OP's case, the expression Coefficient[eq1,a] is evaluated, resulting in x, which results in a rule that would replace eq2[x0] by x0.

The actual rules created may be inspected with DownValues (or ? eq2):

eq1 = a x + b y + c z;   (* note the spaces between a x, etc. *)

eq2[x_] := Coefficient[eq1, a];
DownValues[eq2]
(*  {HoldPattern[eq2[x_]] :> Coefficient[eq1, a]}  *)

eq2[x_] = Coefficient[eq1, a];
DownValues[eq2]
(*  {HoldPattern[eq2[x_]] :> x}  *)

In the first case, eq2[x0] would be replaced by Coefficient[eq1, a].

In the second case, eq2[x0] would be replaced by x0 (since the x in the pattern x_ matches x0).

As noted in a comment to an answer of the linked question, it's a good idea to use Block if there are symbols that should not be evaluated when using Set. In the OP's case, it seems x is to be treated as a symbol. If it had a numeric value at the time eq2[x_] =... is executed, then the definition of eq2[x] would not depend on the argument x.

x = 3;

(* incorrect *)
eq2[x_] = Coefficient[eq1, a];
DownValues[eq2]
(*  {HoldPattern[eq2[x_]] :> 3}  *)

eq2[5]
(*  3  *)

(* correct *)
Block[{x},
  eq2[x_] = Coefficient[eq1, a];
  ];
DownValues[eq2]
(*  {HoldPattern[eq2[x_]] :> x}  *)

eq2[5]
(*  5  *)
$\endgroup$

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