2
$\begingroup$

Simple input like this

f[x_]:=2x
f[2]

has the predicted output of 4. However, this

r={a->2x};
f[x_] := a/.r
f[2]

Produces the output "2 x". I would like it to produce 4. More generally, is there a way I can incorporate rules into a function definition?

$\endgroup$
5
  • 6
    $\begingroup$ f[x_] = a /. r. $\endgroup$
    – cvgmt
    Commented Jun 8, 2022 at 15:15
  • 2
    $\begingroup$ it's not a problem with using rules in the def; it's a problem of whether x literally appears in the rhs or not. When applying a definition where the pattern x_ on the lhs has been matched to an argument, e.g. 2, mathematica looks to see if the pattern name x appears anywhere in the definition's rhs, substitutes, then evaluates. Here it only sees a, /., and r, and no x, so it doesn't substitute anything and finishes its application of the definition. All further evaluation "doesn't know about" the definition anymore. Further... $\endgroup$
    – thorimur
    Commented Jun 9, 2022 at 8:17
  • 2
    $\begingroup$ ...when you use :=, the rhs you typed in is unevaluated, and the definition mathematica learns is the replacement rulef[x_] :> a /. r. When you use =, the rhs is evaluated first, and then learned as a definition—so we start with f[x_] = a /. r, a /. r becomes 2x, then the definition that mathematica learns is the rule f[x_] :> 2x. That's why cvgmt's solution works. See this for more about the difference between := and = :) $\endgroup$
    – thorimur
    Commented Jun 9, 2022 at 8:21
  • $\begingroup$ @thorimur Please turn your comments into an actual answer! It's obviously too long for a comment, as evidenced by the fact that you had to use two :-) It's great insight into what's going wrong, in addition to how to make it right. $\endgroup$
    – MarcoB
    Commented Jun 9, 2022 at 12:16
  • $\begingroup$ @MarcoB Haha, you're absolutely right. And thanks! I've turned them into an answer now. :) $\endgroup$
    – thorimur
    Commented Jun 9, 2022 at 23:08

1 Answer 1

7
$\begingroup$

It's not a problem with using rules in the def; it's a problem of whether x literally appears in the rhs or not.

When applying a definition where the pattern x_ on the lhs has been matched to an argument (e.g. 2), Mathematica looks to see if the pattern name x appears anywhere in the definition's rhs, substitutes the matched value for any x's it finds, then evaluates. Here, it looks at f[2] and matches 2 to x_, then looks at the rhs of the definition, and only sees a, /., and r (and no x). So, it doesn't substitute anything, and finishes its application of the definition. All further evaluation (of a /. r) "doesn't know about" the definition anymore. (In particular, it doesn't know about he value 2 that got matched to x, and x is now "just a symbol again".)

Further, when you use :=, the rhs you typed in is unevaluated, and the definition Mathematica learns is the replacement rule f[x_] :> a /. r. However, when you use =, the rhs is evaluated first, and then learned as a definition. So we start with f[x_] = a /. r, a /. r becomes 2x, then the definition that Mathematica learns is the rule f[x_] :> 2x. That's why cvgmt's solution in the comments (f[x_] = a /. r) works. See this for more about the difference between := and = :)

(Note: I omitted some of the technicalities when describing what rule Mathematica actually learns and how it uses the rule, but all in all, it behaves roughly like :>.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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