# Globally Defining a Variable that Depends on Arguments of Functions [duplicate]

I have many delayed-defined functions of many variables, and all the functions share a term containing some of these variables. Thus, I would like to just call the term x and for each function to immediately read x as that term. What would be the easiest/best/cleanest way to do this?

As a very simplified example, the code

x = a1 + a2;
f[a1_, a2_, a3_] := x + a3
f[b1, b2, b3]


gives the output

a1 + a2 + b3


but the output I want is

b1 + b2 + b3


Given my problem, the following concerns and conditions are understandable.

• I want to avoid defining x explicitly as a function (i.e. x[...]) because it depends on many variables, it would be called many times, and x[...] would end up being almost as large as the term it is supposed to be a shortcut for.

• I want to avoid calling Module[] or Block[] or using replacement rules in each function because I would have to do this for many functions and they are complicated enough as it is. This is why I would like the definition for x to be global.

It seems like there should be a straightforward way for Mathematica to just immediately read a symbol x in each delayed-defined function as a term containing some of the functions' arguments.

## marked as duplicate by Carl Woll, m_goldberg, bbgodfrey, C. E., b3m2a1Nov 3 '18 at 15:24

• Can you just use f[a1_, a2_, a3_] = x + a3? – Carl Woll Oct 25 '18 at 16:17
• I am using delayed-defined functions. – Just Some Old Man Oct 25 '18 at 16:20
• Would something like globalEnvironment[x->a1+a2, f[a1_,a2_, a3_] = x+a3, g[a1_, a2_, a3_] = x^2-a3, ...] work, or do you want to modify how SetDelayed works (i.e., modify a built-in symbol) so that you can just use f[a1_,a2_, a3_] = x+a3; g[a1_, a2_, a3_] = x^2-a3? – Carl Woll Oct 25 '18 at 16:50
• @Carl I would like something like the effects of globalEnvironment, except I wouldn't want to define a large number of big functions inside one function. I don't need to modify SetDelayed overall, except maybe for how it works just the symbol x. – Just Some Old Man Oct 25 '18 at 20:09
• Despite your aversion to Block I believe it is the correct solution here. I consider this question a duplicate of (69590), which I answered with blockSet; please try that before rejecting the idea. – Mr.Wizard Oct 27 '18 at 17:55

This does not avoid defining x as a function, but I believe it meets the required usage nonetheless, and involves no shenanigans with scoping constructs or replacement rules

xpattern = PatternSequence[a1_, a2_];
xfunc[xpattern] = a1 + a2;
f[x : xpattern, a3_] := xfunc[x] + a3


Now we have

f[b1, b2, b3]
(* b1 + b2 + b3 *)


How about modifying $Pre?: $Pre = Function[expr,
Unevaluated[expr] /. a__SetDelayed :> (Unevaluated@a /. OwnValues@x), HoldAll];

x = a1 + a2;
f[a1_, a2_, a3_] := x + a3;
g[a1_, a2_, a3_] := x a3
DownValues /@ {f, g}

(* {{HoldPattern[f[a1_, a2_, a3_]] :> (a1 + a2) + a3},
{HoldPattern[g[a1_, a2_, a3_]] :> (a1 + a2) a3}} *)


Here is another idea. Create an UpValues for x so that using TagSetDelayed with the tag x does what you want:

TagSetDelayed[x, lhs_, rhs_]  ^:= SetDelayed @@ (Hold[lhs, rhs] /. OwnValues[x])


x = a1 + a2;
x /: f[a1_, a2_, a3_] := x + a3


Check:

DownValues[f]


{HoldPattern[f[a1_, a2_, a3_]] :> (a1 + a2) + a3}

• @Mr.Wizard You need to use x /: f[a1_, a2_, a3_] := 1/x + a3, that's the whole point of the TagSetDelayed definition. – Carl Woll Oct 27 '18 at 18:04
• @Mr.Wizard What does ?x return? – Carl Woll Oct 27 '18 at 18:15
• Well nuts, it's working now (in a new session, two hours later) so I guess I had a lingering definition messing things up. Noob mistake! Sorry, and belated +1. ( And to answer your question I get x=a1+a2 (x/:lhs_:=rhs_)^:=SetDelayed@@(Hold[lhs,rhs]/. OwnValues[x]) ) – Mr.Wizard Oct 27 '18 at 21:03