Reply to comment

Batch tricks: Recursion

Aah, recursion, the favorite pet of every programmer. Surely it must be possible to recurse even in Windows batch files (I'm still trying to prove Turing-completeness, by the way :-)).

The first tentative test would be an infinite recursion:

@ECHO OFF
:JUMP
CALL :JUMP

And know what? It works. Well, kinda:

******  B A T C H   R E C U R S I O N  exceeds STACK limits ******
Recursion Count=599, Stack Usage=90 percent
******       B A T C H   PROCESSING IS   A B O R T E D ******

But that's ok, we didn't expect this to do anything useful except of causing a stack overflow. But as we can see, cmd has a stack of some sort and seemingly manages it well enough to allow for recursion.

Time for another test, this time something remotely practical: Factorials. Never mind that those are more easily done with iteration, we want to make sure that recursion works properly:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEX­PANSION

CALL :fac %1
ECHO %RETURN%

:end
ENDLOCAL
GOTO :EOF

:fac
IF %1==0 (
        SET RETURN=1
        GOTO :EOF
)
SET /A TEMP=%1 – 1
CALL :fac %TEMP%
SET /A RETURN*=%1
GOTO :EOF

We need a temporary variable at the end, unfortunately, since cmd does not allow computations inline. But aside from that it looks pretty much how it should. The case for breaking the recursion is also provided in the form of an IF block (sorry, no functional programming niceties, like different function definitions).

But does it work? Oh, sure it does:

> fac 5
120
> fac 10
3628800

And my calculator tells me that those are actually correct. 12! is unfortunately the highest factorial we can compute with it, since we are limited to 32-bit signed integers. A minor bug is still present when using negative numbers, though (infinite recursion, again). This is corrected in the attached version (as well as giving a helpful hint when running the batch without arguments).

Just as a side note, a fun way to implement factorial calculation by leveraging cmd's own „calculator“:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEX­PANSION
SET TEMP=1
FOR /L %%i IN (1,1,%1) DO SET TEMP=!TEMP! * %%<span class=„re2“>i
SET /A TEMP=%TEMP%
ECHO %TEMP%
ENDLOCAL

We simply construct the complete term and evaluate that by using SET /A. Nothing fancy, but probably faster than the recursion.

AttachmentSize
Infinite recursion test28 bytes
Recursive factorial calculation486 bytes
Non-recursive factorial calculation163 bytes

Reply

The content of this field is kept private and will not be shown publicly.