# Can every usage of While be changed into NestWhile?

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.

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

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++]
fibList


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} &

• (+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 ] & Sep 11, 2022 at 13:39