3
$\begingroup$

I'm defining a function in Mathematica as follows:

f[x_] := x+x-x //FullSimplify; 

In this setup, every time f is called, FullSimplify is executed, which can be inefficient. Ideally, I want to precompute the simplification so that the function is defined directly as:

f[x_] := x; 

I prefer using SetDelayed ":=" over Set "=" to prevent interference from any existing values assigned to x. Using Evaluate within SetDelayed also leads to interference. I think using the Hold function is an option, but I'm seeking a more straightforward approach in Mathematica. There has to be a better way?

$\endgroup$
3
  • $\begingroup$ Can you give an example where Set doesn't do what you want? $\endgroup$ Commented Jan 14 at 19:00
  • $\begingroup$ x = 0; f[x_] = x; f[1] This will give me 0 as an output $\endgroup$ Commented Jan 14 at 19:13
  • 1
    $\begingroup$ "I prefer using SetDelayed ":=" over Set "=" to prevent interference from any existing values assigned to x." This is reasonable, but I think the answer to your question really is to just pay attention and use undefined symbols for function definitions. It's good practice anyway to avoid defining symbols as much as possible and cluttering up the NameSpace. Avoid this by using replacement Rule definition instead. That is, rules = {x -> 3} rather than x=3. You'll note that two of the answers use scoping construct Block, which requires you to know which symbols are undefined anyway $\endgroup$ Commented Jan 14 at 19:49

3 Answers 3

7
$\begingroup$

This is a good place to use Formal symbols which cannot take on a value, and therefore avoid the risk of x = 3; f[x_] = x which is typically what you don't want.

Try this instead:

f[\[FormalX]_] = Simplify[Echo[Nest[1/(1 + #) &, \[FormalX], 10]]] 

The following never computes the nested function

f[x] f[12] ?f 
$\endgroup$
3
  • 1
    $\begingroup$ Try Block[{\[FormalX] = 3}, f[\[FormalX]_] = \[FormalX]]; f[1] $\endgroup$ Commented Jan 15 at 0:32
  • $\begingroup$ How interesting: Block allows a set to a formal symbol. That is sequentiality non-obvious and then obvious. Your answer is bullet proof; mine isn't. $\endgroup$ Commented Jan 15 at 4:48
  • 2
    $\begingroup$ I was surprised, too, some years back when I discovered it. Locked symbols cannot be blocked in this way, but Protected symbols can: Block[{List = Plus}, {}] vs. Block[{Plus = Times}, Plus[]]. $\endgroup$ Commented Jan 15 at 11:56
7
$\begingroup$

I think you could do this by combining Block and Evaluate:

x = 1; Block[ {x}, h[x_] := Evaluate[FullSimplify[x + x - x]]]; DownValues[h] (* {HoldPattern[h[x_]] :> x} *) 

You could also take advantage of formal symbols:

g[\[FormalX]_] = FullSimplify[\[FormalX] + \[FormalX] - \[FormalX]] 

That assumes you haven't unprotected \[FormalX].

You could also use a Function instead, if there's a way to use Slots instead of named arguments:

k = Function[, Evaluate[FullSimplify[# + # - #]]] 
$\endgroup$
6
$\begingroup$

I manually Block[] the variables:

x = 0; Block[{x}, f[x_] = x - x + x; ] f[1] (* 1 *) DownValues[f] (* {HoldPattern[f[x_]] :> x} *) 

It means you have to know what variables to block.

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.