I’d like to set the constants in a function that uses If, after it’s been defined, but my definitions doesn’t seem to stick. Simple example:

f[x_] := If[x < 1, f1, f2] f[x] (* If[x < 1, f1, f2] *) {f1, f2} = {-1, 1}; f[x] (* If[x < 1, f1, f2] *) Instead of the last one, I want to get If[x < 1, -1, 1] Any ideas how? I have a feeling this should be easy but it's hard to search for. ================= 1 Why not define f to have f1 and f2 as its parameters at the outset? f[f1_, f2_, x_] := (* stuff *) – J. M.♦ Jun 18 '15 at 21:10 1 You have to give x a value when you call f, otherwise the truth of the test in If cannot be determined and Mathematica returns it as it got it. – Sjoerd C. de Vries Jun 18 '15 at 21:18 ================= 2 Answers 2 ================= If has attribute HoldRest: Attributes[If] (* {HoldRest, Protected} *) and so the second and third arguments are not evaluated unless If chooses to do so, which, unless the first argument evaluates to True or False, it does not. You can use With to insert the defined values of f1 and f2 prior to evaluation: Clear[f, f1, f2]; f[x_] := With[{f1 = f1, f2 = f2}, If[x < 1, f1, f2]] f[x] (* If[x < 1, f1, f2] *) {f1, f2} = {-1, 1}; f[x] (* If[x < 1, -1, 1] *) The odd-looking syntax in the first argument of With works because only the right-hand sides of the assignments are evaluated. Thanks, I wouldn't have guessed that! – Chris K Jun 18 '15 at 23:45 Another workaround (inspired by Simon Rochester's observation about If's HoldRest attribute) -- make a "new" If without that attribute: If2[a_, b_, c_] := If[a, b, c]; f[x_] := If2[x < 1, f1, f2] f[x] (*If[x<1,f1,f2]*) {f1, f2} = {-1, 1}; f[x] (*If[x<1,-1,1]*) (seems safer than changing the real If!)