Update a function avoiding infinite recursion


I am quite new to Mathematica and not completely familiar with functional programming. I am currently working with a function (call it foo) and wish to change its behaviour, for example, by adding 1 to its output. Obviously writing

foo = (foo[#]+1)&;


foo[x_] := foo[x] + 1;

leads to an infinite recursion as soon as I try to evaluate the function. To be more explicit, if at the beginning foo[1] returns 1 and foo[2] returns 3, I would like the output to be 2 and 4 respectively after the change.

Is there any way to easily obtain this behaviour with Mathematica?

I apologize if the question is a duplicate, but I did not find anything similar already posted.


Posted 2013-03-21T16:03:42.460

Reputation: 183

1Why not defining a foo2[x_] = foo[x] + 1 ? – b.gates.you.know.what – 2013-03-21T16:08:27.893

The line of code is thought to be inside a loop and I need to, so to say, update the function before iterating. – Stefano – 2013-03-21T16:14:09.310



If you absolutely have to use the same name for the function, and add new behavior, then you have several options. A special device invented for this sort of situations is called Villegas-Gayley technique. In this particular case, it will look like

foo[n_] := 2*n - 1;

foo[x_] /; ! TrueQ[inFoo] := Block[{inFoo = True}, foo[x] + 1]

where the last definition is the one which alters the behavior. You can test:

foo /@ {1, 2}

(* {2, 4} *)

However, this won't always work. For example, this won't work if your function has been defined specifically on these values:

foo[1] = 1;
foo[2] = 3;

Adding this definition now

foo[x_] /; ! TrueQ[inFoo] := Block[{inFoo = True}, foo[x] + 1]

won't help:

foo /@ {1, 2}

(* {1, 3} *)

The reasons for that have to do with the relative specificity of various patterns, and the fact that a function defined on specific values has a different (hash-table - based) representation which is hard to override.

In this case, I suggest to use a rather heavy-handed approach I described here. Using functions from it, we have:

  {foo[x_] /; ! TrueQ[inFoo] := Block[{inFoo = True}, foo[x] + 1]},
  foo /@ {1, 2}

(* {2, 4} *)

However, best would be to reconsider your design and needs, since chances are that you don't really need any of these methods, and can find a solution by more traditional means.

Leonid Shifrin

Posted 2013-03-21T16:03:42.460

Reputation: 108 027

Thank you very much for the quick answer, which solved the issue. Is it right to say that the trick is able to "freeze" further evaluations of the function because after the first call to foo the flag inFoo is set to True and therefore the condition ! TrueQ[inFoo] necessary to evaluating foo cannot be further met? – Stefano – 2013-03-22T00:18:25.980

@Stefano Yes, this is exactly what happens. Glad I could help. Thanks for the accept. – Leonid Shifrin – 2013-03-22T00:30:57.467

Sorry for writing again, but checking further the results, I noticed that some problems are still around. If I try ClearAll[foo] foo[n_] := 2*n - 1; For[i = 0, i < 10, i++, ClearAll[inFoo]; foo[x_] /; ! TrueQ[inFoo] := Block[{inFoo = True}, foo[x] + 1]; Print[foo[2]] ] the output is 3, 4, 4, 4... with the function being updated only once. Is this the behaviour expected? – Stefano – 2013-03-22T01:07:09.653

@Stefano Yes, it is expected. Try to figure out on your own why this is so. I also think that whatever your problem is, you should be able to solve it without the rather heavy machinery I described in my post. – Leonid Shifrin – 2013-03-22T02:08:59.373


Do you mean you need to update the definition of the function in terms of the previous definition? I do not get infinite recursion when doing the following:

Mathematica graphics

Make sure x has no assigned value when you do this, and use = (not :=) to allow the previous definition to expand.

All this said, it is not a good idea to do this in most cases, and there should be alternative solutions (depending on the problem).


Posted 2013-03-21T16:03:42.460

Reputation: 213 047

Does this answer your question at all? I'm not sure I understand it. Leonid's answer is interesting and useful, but it's not really a basic one. I thought it's educational to add this very basic comment. – Szabolcs – 2013-03-21T20:11:42.083

Thank you very much for the remark. Actually, I meant the definition with := instead of =. Indeed, the last does not seem to give problems in the simple example above.

I am quite new to functional programming in general. I am try to implement some kind of fixed point algorithm where the unknown are functions: what design would you suggest in this case? (obviously the issue above is an outcome of my background in procedural programming) – Stefano – 2013-03-22T00:29:52.353