1
$\begingroup$

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[10]

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$?

$\endgroup$
3
  • $\begingroup$ Because I want to assign the new value of x+2 to x, for further use. $\endgroup$ – Kieran Cooney Jun 26 '14 at 21:24
  • $\begingroup$ 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? $\endgroup$ – Szabolcs Jun 26 '14 at 21:25
  • $\begingroup$ You're right; thanks for your correction. $\endgroup$ – Kieran Cooney Jun 26 '14 at 21:27
5
$\begingroup$

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]
$\endgroup$
2
$\begingroup$

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[5] may be of little value at top level, it makes sense for 1 + f[5] 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[5]; 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[5], f[1 + Sqrt[2]], f[π]}
{7, 3 + Sqrt[2], 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}]}
$\endgroup$
1
  • $\begingroup$ complete treatment $\endgroup$ – acl Jun 27 '14 at 0:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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