# Using AddTo in a function

I want to create a function that will take a variable $x$ and reassign the value $x+2$ to $x$.

So

f[x_]:= x += 2


However:

f


yields the Mathematica error

AddTo::rvalue: 10 is not a variable with a value, so its value cannot be changed.

Which makes sense, as I am asking Mathematica to assign the value of 12 to 10. So how can I do this so that it changes the assigned value of some variable $x$?

• Because I want to assign the new value of x+2 to x, for further use. – Kieran Cooney Jun 26 '14 at 21:24
• I realize that now, but that's not what your first sentence says. It says "I want to create a function that will take a variable x and return x+2.", not "I want to create a function that will take a variable and re-assign its value." Could you clarify the post a bit? – Szabolcs Jun 26 '14 at 21:25
• You're right; thanks for your correction. – Kieran Cooney Jun 26 '14 at 21:27

## 2 Answers

You can set f to hold its arguments, like so:

ClearAll[f];
SetAttributes[f, HoldAll]
f[x_] := x += 2


Then

x = 5
f[x]
x


evaluates to

(*
5
7
7
*)


You can also use the third argument of Function for this, like so:

f = Function[{z}, z += 2, HoldAll]


Let's pretend that f is going to be a function that will see serious use. For such functions, we must consider not only normal use cases, but also edge cases and outright abuse. And we must also consider how f will act in combination with other functions.

For this particular case, we might reason that f that, while f may be of little value at top level, it makes sense for 1 + f to evaluate to 8. Further, we might want to handle the edge case where x is value-free in the same way we would handle f; e.g. return 2 + x. And finally we would want to print out a normal looking Mathematica style error message for abusive use such as f[] and f["string"].

ClearAll[f, x, y]
f::badarg = "f requires a symbol with a value or numeric value for its argument";
SetAttributes[f, HoldFirst]
f[x_Symbol] /; ValueQ[x] := x += 2
f[x : (_Symbol | _? NumericQ)] := x + 2
f[args : ___] := (Message[f::badarg]; Defer[f[args]])


Unit tests

Normal cases

x = 40; {f[x], x}

{42, 42}

{f, f[1 + Sqrt], f[π]}

{7, 3 + Sqrt, 2 + π}


Edge case (y has no assigned value)

f[y]

2 + y


Abuse

{f["string"], f[{1, 2, 3}]}


f::badarg: f requires a symbol with a value or numeric value for its argument
f::badarg: f requires a symbol with a value or numeric value for its argument

{f["string"], f[{1, 2, 3}]}

• complete treatment – acl Jun 27 '14 at 0:06