OK, I think this problem is more close to philosophy. :P

I've some idea now. But I'm not sure whether it's correct. For the purpose of convenience, I will use some C-like code instead of Mathematica's.

A While loop is something like:

i=0; // some initialize of variable i
While(test of variable i)   // such like i<10 or i^3<90, etc.
   // involving doing something which has nothing to do with i (e.g. Print["*"])
   // or involving taking i as an argument of another function, such like Sin[i]
   // or involving re-assign some value to i, such like i=i+7
Print[i] // after doing such evaluations, we want to get the final value of i

The first and second line surrounded in while is not really a problem for NestWhile. It is just because NestWhile is NestWhile[f, expr, test], one can write (Print["*"]; Sin[#] + 1 &) in the place of f, doing the same thing you want when you're dealing with While.

However, when you want to re-assign expr in NestWhile, No, you cannot. i = 0; NestWhile[# = # + 1 &, i, # < 70 &] is not what you want. (The i is immediately change into 0 before you would want to do i = i+1)

And just because of this simple difference between While and NestWhile, I doubt that EVERY While-code can change into NestWhile-code.

  • $\begingroup$ In my experience, While is very easy to compile, but NestWhile is not. $\endgroup$ Aug 9, 2014 at 17:02

2 Answers 2


Taking the question at face value, I think the answer is yes. A While loop

While[test, body]

evaluates test then body until test fails to give True. This can be implemented in NestWhile by putting test and body into Functions:

NestWhile[body &, Null, test &]

For example the following both do the same thing:

i = 0; While[i < 10, i++];
i = 0; NestWhile[(i++) &, Null, (i < 10) &];

I don't think this is what you are after though. In the question you describe a restricted subset of While loops in which body consists of "doing stuff with some variable i" and test consists of "a function of i". The question, I think, is whether such While loops can be converted to NestWhile with the variable i used as the expr (i.e. second argument) in NestList.

As you pointed out, this is not easily done. Here is a possible approach using Hold to prevent unwanted evaluations:

i = 0;
NestWhile[((Increment @@ #); #) &, Hold[i], ReleaseHold[#] < 10 &]

This is pretty horrible. Not only do we have to jump through hoops to evaluate i++ without prematurely evaluating i, the iterated function now takes Hold[i] as input and returns the same Hold[i] as output. The whole principle of functional iteration has been murdered just to allow us to (awkwardly) manipulate the global symbol i as a side effect.

In summary the answer is yes, you can change every usage of While into NestWhile, but you shouldn't. NestWhile's purpose is to implement functional iteration - don't think of it as a special case of While, think of it as a special case of Nest.


One approach to change While to NestWhile is to incorporate variable increments, such as i++, as part the repeated function application. The idea of incorporating increments is similar to what Simon Woods proposed.

You can go a step further and roll the initialisation into Nestwhile as well--closer in spirit perhaps to a functional version.

Example for Fibonacci numbers:

The function fib generates the k-th fibonacci number:

fib[k_] := Nest[{#[[2]], #[[1]] + #[[2]]} &, {0, 1}, k][[2]]

The following While-code produces the list of fibonacci numbers valued strictly below 10:

n = 0;
fibList = {};
While[fib[n] < 10, fibList = Join[fibList, {fib[n]}]; n++]

output: {1, 1, 2, 3, 5, 8}

Compare this with a NestWhile implementation producing the same output:

NestWhile[{Join[#[[1]], {fib[#[[2]]]}], #[[2]] + 1} &, {{}, 0}, 
  fib[#[[2]]] < 10 &][[1]]

The initialisation value is {{ },0}

The nested function is Join[#[[1]], {fib[#[[2]]]}], #[[2]] + 1} &

  • 2
    $\begingroup$ (+1) I would describe the conversion from While[] to NestWhile[] in terms "state variables," but that's to do with my background which is not CS: NestWhile[ Apply@Function[ statevariables, body ], initialvalues, Apply@Function[ statevariables, test ]] // First. For instance, in your example statevariables becomes {fibList, n} and body becomes {Join[fibList, {fib[n]}], n + 1}; and test becomes fib[n] < 10. One could also do a more direct translation like this: Block[ statevariables, statevariables = #; whilebody; statevariables ] & $\endgroup$
    – Michael E2
    Sep 11, 2022 at 13:39

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.