Find limit of recursion: Difference between revisions
Content added Content deleted
Puppydrum64 (talk | contribs) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 13: | Line 13: | ||
Reading the current stack pointer is unreliable, as there is no requirement that the stack be "aligned" in any way. Unlike the 8086 and Z80, which require all pushes/pops to be exactly two bytes, the 6502's stack will likely contain both 1 byte registers and 2 byte return addresses. It's much easier to use a stack canary. Pick a value that is unlikely to be used in your program. |
Reading the current stack pointer is unreliable, as there is no requirement that the stack be "aligned" in any way. Unlike the 8086 and Z80, which require all pushes/pops to be exactly two bytes, the 6502's stack will likely contain both 1 byte registers and 2 byte return addresses. It's much easier to use a stack canary. Pick a value that is unlikely to be used in your program. |
||
< |
<syntaxhighlight lang="6502asm">;beginning of your program |
||
lda #$BE |
lda #$BE |
||
sta $0100 |
sta $0100 |
||
Line 27: | Line 27: | ||
lda $0100 ;if this no longer equals $BE the stack has overflowed |
lda $0100 ;if this no longer equals $BE the stack has overflowed |
||
cmp #$BE |
cmp #$BE |
||
bne StackHasOverflowed</ |
bne StackHasOverflowed</syntaxhighlight> |
||
=={{header|8080 Assembly}}== |
=={{header|8080 Assembly}}== |
||
Line 51: | Line 51: | ||
at run-time, at the cost of some overhead per call. |
at run-time, at the cost of some overhead per call. |
||
< |
<syntaxhighlight lang="8080asm"> org 100h |
||
lxi b,0 ; BC holds the amount of calls |
lxi b,0 ; BC holds the amount of calls |
||
call recur ; Call the recursive routine |
call recur ; Call the recursive routine |
||
Line 99: | Line 99: | ||
;;; If the guard is overwritten, the stack has overflowed. |
;;; If the guard is overwritten, the stack has overflowed. |
||
GUARD: equ $+2 ; Make sure it is not a valid return address |
GUARD: equ $+2 ; Make sure it is not a valid return address |
||
guard: dw GUARD</ |
guard: dw GUARD</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 120: | Line 120: | ||
of calls you can make before the stack is full (and would overwrite your program). |
of calls you can make before the stack is full (and would overwrite your program). |
||
< |
<syntaxhighlight lang="8080asm"> org 100h |
||
lxi h,-top ; Subtract highest used location from stack pointer |
lxi h,-top ; Subtract highest used location from stack pointer |
||
dad sp |
dad sp |
||
Line 159: | Line 159: | ||
;;; This means anything from this place up to SP is free for the |
;;; This means anything from this place up to SP is free for the |
||
;;; stack. |
;;; stack. |
||
top: equ $ </ |
top: equ $ </syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 166: | Line 166: | ||
=={{header|ACL2}}== |
=={{header|ACL2}}== |
||
< |
<syntaxhighlight lang="lisp">(defun recursion-limit (x) |
||
(if (zp x) |
(if (zp x) |
||
0 |
0 |
||
(prog2$ (cw "~x0~%" x) |
(prog2$ (cw "~x0~%" x) |
||
(1+ (recursion-limit (1+ x))))))</ |
(1+ (recursion-limit (1+ x))))))</syntaxhighlight> |
||
{{out}} (trimmed): |
{{out}} (trimmed): |
||
Line 187: | Line 187: | ||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO; |
||
procedure Test_Recursion_Depth is |
procedure Test_Recursion_Depth is |
||
Line 199: | Line 199: | ||
begin |
begin |
||
Put_Line ("Recursion depth on this system is" & Integer'Image (Recursion (1))); |
Put_Line ("Recursion depth on this system is" & Integer'Image (Recursion (1))); |
||
end Test_Recursion_Depth;</ |
end Test_Recursion_Depth;</syntaxhighlight> |
||
Note that unlike some solutions in other languages this one does not crash (though usefulness of this task is doubtful). |
Note that unlike some solutions in other languages this one does not crash (though usefulness of this task is doubtful). |
||
Line 218: | Line 218: | ||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
The depth of recursion in Algol 68 proper is unlimited. Particular implementations will reach a limit, if only through exhaustion of storage and/or address space and/or time before power failure. If not time limited, the depth reached depends very much on what the recursive routine needs to store on the stack, including local variables if any. The simplest recursive Algol68 program is: |
The depth of recursion in Algol 68 proper is unlimited. Particular implementations will reach a limit, if only through exhaustion of storage and/or address space and/or time before power failure. If not time limited, the depth reached depends very much on what the recursive routine needs to store on the stack, including local variables if any. The simplest recursive Algol68 program is: |
||
< |
<syntaxhighlight lang="algol68">PROC recurse = VOID : recurse; recurse</syntaxhighlight> |
||
This one-liner running under Algol68 Genie and 64-bit Linux reaches a depth of 3535 with the shell's default stack size of 8Mbytes and 28672 when set to 64Mbytes, |
This one-liner running under Algol68 Genie and 64-bit Linux reaches a depth of 3535 with the shell's default stack size of 8Mbytes and 28672 when set to 64Mbytes, |
||
as shown by the following output. From this we can deduce that Genie does not implement tail recursion. The --trace option to a68g prints a stack trace when the program crashes; the first two commands indicate the format of the trace, the third counts the depth of recursion with the default stack size and the fourth shows the result of octupling the size of the stack. |
as shown by the following output. From this we can deduce that Genie does not implement tail recursion. The --trace option to a68g prints a stack trace when the program crashes; the first two commands indicate the format of the trace, the third counts the depth of recursion with the default stack size and the fourth shows the result of octupling the size of the stack. |
||
Line 255: | Line 255: | ||
===Test 1=== |
===Test 1=== |
||
A basic test for Applescript, which has a notoriously shallow recursion stack. |
A basic test for Applescript, which has a notoriously shallow recursion stack. |
||
< |
<syntaxhighlight lang="applescript">-- recursionDepth :: () -> IO String |
||
on recursionDepth() |
on recursionDepth() |
||
script go |
script go |
||
Line 274: | Line 274: | ||
recursionDepth() |
recursionDepth() |
||
end run</ |
end run</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>"Recursion limit encountered at 502"</pre> |
<pre>"Recursion limit encountered at 502"</pre> |
||
Line 280: | Line 280: | ||
===Test 2=== |
===Test 2=== |
||
We get a fractionally higher (and arguably purer) result by deriving the highest Church Numeral (Church-encoded integer) that can be represented using AppleScript: |
We get a fractionally higher (and arguably purer) result by deriving the highest Church Numeral (Church-encoded integer) that can be represented using AppleScript: |
||
< |
<syntaxhighlight lang="applescript">-- HIGHEST CHURCH NUMERAL REPRESENTABLE IN APPLESCRIPT ? |
||
-- (This should be a good proxy for recursion depth) |
-- (This should be a good proxy for recursion depth) |
||
Line 373: | Line 373: | ||
on succ(x) |
on succ(x) |
||
1 + x |
1 + x |
||
end succ</ |
end succ</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>"The highest Church-encoded integer representable in Applescript is 571"</pre> |
<pre>"The highest Church-encoded integer representable in Applescript is 571"</pre> |
||
Line 384: | Line 384: | ||
Testing with no local variables and with an external 'try' statement, the maximum recursion depth possible appears to be 733. (732 if the code below's run as an applet instead of in an editor or from the system script menu.) So, depending on what a script actually does, the limit can be anything between <502 and 733. In practice, it's very difficult for well written AppleScript code to run out of stack. |
Testing with no local variables and with an external 'try' statement, the maximum recursion depth possible appears to be 733. (732 if the code below's run as an applet instead of in an editor or from the system script menu.) So, depending on what a script actually does, the limit can be anything between <502 and 733. In practice, it's very difficult for well written AppleScript code to run out of stack. |
||
< |
<syntaxhighlight lang="applescript">global i |
||
on recursion() |
on recursion() |
||
Line 399: | Line 399: | ||
-- display dialog result -- Uncomment to see the result if running as an applet. |
-- display dialog result -- Uncomment to see the result if running as an applet. |
||
end try |
end try |
||
end run</ |
end run</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
< |
<syntaxhighlight lang="applescript">"Recursion limit encountered at 733"</syntaxhighlight> |
||
=={{header|Arturo}}== |
=={{header|Arturo}}== |
||
< |
<syntaxhighlight lang="rebol">recurse: function [x][ |
||
print x |
print x |
||
recurse x+1 |
recurse x+1 |
||
] |
] |
||
recurse 0</ |
recurse 0</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 425: | Line 425: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="autohotkey">Recurse(0) |
||
Recurse(x) |
Recurse(x) |
||
Line 431: | Line 431: | ||
TrayTip, Number, %x% |
TrayTip, Number, %x% |
||
Recurse(x+1) |
Recurse(x+1) |
||
}</ |
}</syntaxhighlight> |
||
Last visible number is 827. |
Last visible number is 827. |
||
=={{header|AutoIt}}== |
=={{header|AutoIt}}== |
||
< |
<syntaxhighlight lang="autoit">;AutoIt Version: 3.2.10.0 |
||
$depth=0 |
$depth=0 |
||
recurse($depth) |
recurse($depth) |
||
Line 442: | Line 442: | ||
ConsoleWrite($depth&@CRLF) |
ConsoleWrite($depth&@CRLF) |
||
Return recurse($depth+1) |
Return recurse($depth+1) |
||
EndFunc</ |
EndFunc</syntaxhighlight> |
||
Last value of $depth is 5099 before error. |
Last value of $depth is 5099 before error. |
||
Error: Recursion level has been exceeded - AutoIt will quit to prevent stack overflow. |
Error: Recursion level has been exceeded - AutoIt will quit to prevent stack overflow. |
||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
< |
<syntaxhighlight lang="awk"># syntax: GAWK -f FIND_LIMIT_OF_RECURSION.AWK |
||
# |
# |
||
# version depth messages |
# version depth messages |
||
Line 468: | Line 468: | ||
if (n > 999999) { return } |
if (n > 999999) { return } |
||
x() |
x() |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Axe}}== |
=={{header|Axe}}== |
||
Line 475: | Line 475: | ||
In Axe 1.2.2 on a TI-84 Plus Silver Edition, the last line this prints before hanging is 12520. This should be independent of any arguments passed since they are not stored on the stack. |
In Axe 1.2.2 on a TI-84 Plus Silver Edition, the last line this prints before hanging is 12520. This should be independent of any arguments passed since they are not stored on the stack. |
||
< |
<syntaxhighlight lang="axe">RECURSE(1) |
||
Lbl RECURSE |
Lbl RECURSE |
||
.Optionally, limit the number of times the argument is printed |
.Optionally, limit the number of times the argument is printed |
||
Disp r₁▶Dec,i |
Disp r₁▶Dec,i |
||
RECURSE(r₁+1)</ |
RECURSE(r₁+1)</syntaxhighlight> |
||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
==={{header|Applesoft BASIC}}=== |
==={{header|Applesoft BASIC}}=== |
||
Each GOSUB consumes 6 bytes of stack space and when more than 25 levels have been reached and an <code>?OUT OF MEMORY ERROR</code> message is displayed. |
Each GOSUB consumes 6 bytes of stack space and when more than 25 levels have been reached and an <code>?OUT OF MEMORY ERROR</code> message is displayed. |
||
< |
<syntaxhighlight lang="applesoftbasic"> 100 PRINT "RECURSION DEPTH" |
||
110 PRINT D" "; |
110 PRINT D" "; |
||
120 LET D = D + 1 |
120 LET D = D + 1 |
||
130 GOSUB 110"RECURSION</ |
130 GOSUB 110"RECURSION</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>RECURSION DEPTH |
<pre>RECURSION DEPTH |
||
Line 496: | Line 496: | ||
Utterly dependent on the stack size and RAM available to the process. |
Utterly dependent on the stack size and RAM available to the process. |
||
< |
<syntaxhighlight lang="freebasic">' Recursion limit |
||
FUNCTION recurse(i) |
FUNCTION recurse(i) |
||
PRINT i |
PRINT i |
||
Line 503: | Line 503: | ||
END FUNCTION |
END FUNCTION |
||
extraneous = recurse(0)</ |
extraneous = recurse(0)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 517: | Line 517: | ||
==={{header|BASIC256}}=== |
==={{header|BASIC256}}=== |
||
< |
<syntaxhighlight lang="freebasic">function Recursion(i) |
||
print i |
print i |
||
ext = Recursion(i + 1) |
ext = Recursion(i + 1) |
||
Line 523: | Line 523: | ||
end function |
end function |
||
ext = Recursion(0)</ |
ext = Recursion(0)</syntaxhighlight> |
||
==={{header|FreeBASIC}}=== |
==={{header|FreeBASIC}}=== |
||
< |
<syntaxhighlight lang="freebasic">sub sisyphus( n as ulongint ) |
||
print n |
print n |
||
sisyphus( 1 + n ) |
sisyphus( 1 + n ) |
||
end sub |
end sub |
||
sisyphus(0)</ |
sisyphus(0)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 544: | Line 544: | ||
==={{header|GW-BASIC}}=== |
==={{header|GW-BASIC}}=== |
||
< |
<syntaxhighlight lang="gwbasic">10 N#=0 |
||
20 N# = N# + 1 |
20 N# = N# + 1 |
||
30 LOCATE 1,1:PRINT N# |
30 LOCATE 1,1:PRINT N# |
||
40 GOSUB 20</ |
40 GOSUB 20</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 555: | Line 555: | ||
==={{header|QBasic}}=== |
==={{header|QBasic}}=== |
||
{{works with|QBasic|1.1}} |
{{works with|QBasic|1.1}} |
||
< |
<syntaxhighlight lang="qbasic">FUNCTION Recursion (i) |
||
PRINT i |
PRINT i |
||
ext = Recursion(i + 1) |
ext = Recursion(i + 1) |
||
Line 561: | Line 561: | ||
END FUNCTION |
END FUNCTION |
||
ext = Recursion(0)</ |
ext = Recursion(0)</syntaxhighlight> |
||
==={{header|Sinclair ZX81 BASIC}}=== |
==={{header|Sinclair ZX81 BASIC}}=== |
||
The only limit is the available memory. |
The only limit is the available memory. |
||
< |
<syntaxhighlight lang="basic">10 LET D=0 |
||
20 GOSUB 30 |
20 GOSUB 30 |
||
30 PRINT AT 0,0;D |
30 PRINT AT 0,0;D |
||
40 LET D=D+1 |
40 LET D=D+1 |
||
50 GOSUB 30</ |
50 GOSUB 30</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Run with 1k of RAM: |
Run with 1k of RAM: |
||
Line 578: | Line 578: | ||
==={{header|Tiny BASIC}}=== |
==={{header|Tiny BASIC}}=== |
||
< |
<syntaxhighlight lang="tiny basic">10 LET N = -32767 |
||
20 LET M = 0 |
20 LET M = 0 |
||
30 LET N = N + 1 |
30 LET N = N + 1 |
||
Line 584: | Line 584: | ||
50 IF N = 32767 THEN PRINT M," x 2^16" |
50 IF N = 32767 THEN PRINT M," x 2^16" |
||
60 IF N = 32767 THEN LET N = -N |
60 IF N = 32767 THEN LET N = -N |
||
70 GOSUB 30</ |
70 GOSUB 30</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>1 x 2^16 |
<pre>1 x 2^16 |
||
Line 600: | Line 600: | ||
{{works with|BASIC256}} |
{{works with|BASIC256}} |
||
{{works with|QBasic}} |
{{works with|QBasic}} |
||
< |
<syntaxhighlight lang="qbasic">FUNCTION Recursion (i) |
||
PRINT i |
PRINT i |
||
LET ext = Recursion(i + 1) |
LET ext = Recursion(i + 1) |
||
Line 607: | Line 607: | ||
LET ext = Recursion(0) |
LET ext = Recursion(0) |
||
END</ |
END</syntaxhighlight> |
||
==={{header|XBasic}}=== |
==={{header|XBasic}}=== |
||
{{works with|Windows XBasic}} |
{{works with|Windows XBasic}} |
||
< |
<syntaxhighlight lang="xbasic">PROGRAM "Find limit of recursion" |
||
DECLARE FUNCTION Entry () |
DECLARE FUNCTION Entry () |
||
Line 625: | Line 625: | ||
END FUNCTION |
END FUNCTION |
||
END PROGRAM</ |
END PROGRAM</syntaxhighlight> |
||
==={{header|Yabasic}}=== |
==={{header|Yabasic}}=== |
||
< |
<syntaxhighlight lang="freebasic">sub Recursion(i) |
||
print i |
print i |
||
Recursion(i + 1) |
Recursion(i + 1) |
||
end sub |
end sub |
||
Recursion(0)</ |
Recursion(0)</syntaxhighlight> |
||
==={{header|ZX Spectrum Basic}}=== |
==={{header|ZX Spectrum Basic}}=== |
||
On the ZX Spectrum recursion is limited only by stack space. The program eventually fails, because the stack is so full that there is no stack space left to make the addition at line 110: |
On the ZX Spectrum recursion is limited only by stack space. The program eventually fails, because the stack is so full that there is no stack space left to make the addition at line 110: |
||
< |
<syntaxhighlight lang="zxbasic">10 LET d=0: REM depth |
||
100 PRINT AT 1,1; "Recursion depth: ";d |
100 PRINT AT 1,1; "Recursion depth: ";d |
||
110 LET d=d+1 |
110 LET d=d+1 |
||
120 GO SUB 100: REM recursion |
120 GO SUB 100: REM recursion |
||
130 RETURN: REM this is never reached |
130 RETURN: REM this is never reached |
||
200 STOP</ |
200 STOP</syntaxhighlight> |
||
{{out}}(from a 48k Spectrum): |
{{out}}(from a 48k Spectrum): |
||
<pre> Recursion depth: 13792 |
<pre> Recursion depth: 13792 |
||
Line 650: | Line 650: | ||
MUNG.CMD is a commandline tool written in DOS Batch language. It finds the limit of recursion possible using CMD /C. |
MUNG.CMD is a commandline tool written in DOS Batch language. It finds the limit of recursion possible using CMD /C. |
||
< |
<syntaxhighlight lang="dos">@echo off |
||
set /a c=c+1 |
set /a c=c+1 |
||
echo [Depth %c%] Mung until no good |
echo [Depth %c%] Mung until no good |
||
cmd /c mung.cmd |
cmd /c mung.cmd |
||
echo [Depth %c%] No good |
echo [Depth %c%] No good |
||
set /a c=c-1</ |
set /a c=c-1</syntaxhighlight> |
||
Result (abbreviated): |
Result (abbreviated): |
||
Line 672: | Line 672: | ||
If one uses <code>call</code> rather than <code>CMD/C</code>, the call depth is much deeper but ends abruptly and can't be trapped. |
If one uses <code>call</code> rather than <code>CMD/C</code>, the call depth is much deeper but ends abruptly and can't be trapped. |
||
< |
<syntaxhighlight lang="dos">@echo off |
||
set /a c=c+1 |
set /a c=c+1 |
||
echo [Depth %c%] Mung until no good |
echo [Depth %c%] Mung until no good |
||
call mung.cmd |
call mung.cmd |
||
echo [Depth %c%] No good |
echo [Depth %c%] No good |
||
set /a c=c-1</ |
set /a c=c-1</syntaxhighlight> |
||
Result (abbreviated): |
Result (abbreviated): |
||
Line 691: | Line 691: | ||
You also get the exact same results when calling mung internally, as below |
You also get the exact same results when calling mung internally, as below |
||
< |
<syntaxhighlight lang="dos">@echo off |
||
set c=0 |
set c=0 |
||
:mung |
:mung |
||
Line 698: | Line 698: | ||
call :mung |
call :mung |
||
set /a c=c-1 |
set /a c=c-1 |
||
echo [Level %c%] No good</ |
echo [Level %c%] No good</syntaxhighlight> |
||
Setting a limit on the recursion depth can be done like this: |
Setting a limit on the recursion depth can be done like this: |
||
< |
<syntaxhighlight lang="dos">@echo off |
||
set c=0 |
set c=0 |
||
:mung |
:mung |
||
Line 710: | Line 710: | ||
call :mung %c% |
call :mung %c% |
||
set /a c=%1-1 |
set /a c=%1-1 |
||
echo [Level %c%] No good</ |
echo [Level %c%] No good</syntaxhighlight> |
||
=={{header|BBC BASIC}}== |
=={{header|BBC BASIC}}== |
||
< |
<syntaxhighlight lang="bbcbasic"> PROCrecurse(1) |
||
END |
END |
||
Line 719: | Line 719: | ||
IF depth% MOD 100 = 0 PRINT TAB(0,0) depth%; |
IF depth% MOD 100 = 0 PRINT TAB(0,0) depth%; |
||
PROCrecurse(depth% + 1) |
PROCrecurse(depth% + 1) |
||
ENDPROC</ |
ENDPROC</syntaxhighlight> |
||
{{out}} from BBC BASIC for Windows with default value of HIMEM: |
{{out}} from BBC BASIC for Windows with default value of HIMEM: |
||
<pre> |
<pre> |
||
Line 732: | Line 732: | ||
Most interpreters allocate their stack on the global heap, so the size of the stack will depend on available memory, and on a modern system you're likely to run out of patience long before you run out of memory. That said, there have been some interpreters with a fixed stack depth - as low as 199 even - but that isn't a common implementation choice. |
Most interpreters allocate their stack on the global heap, so the size of the stack will depend on available memory, and on a modern system you're likely to run out of patience long before you run out of memory. That said, there have been some interpreters with a fixed stack depth - as low as 199 even - but that isn't a common implementation choice. |
||
< |
<syntaxhighlight lang="befunge">1>1#:+#.:_@</syntaxhighlight> |
||
=={{header|BQN}}== |
=={{header|BQN}}== |
||
Tested with the [[CBQN]] REPL on Ubuntu Linux. |
Tested with the [[CBQN]] REPL on Ubuntu Linux. |
||
< |
<syntaxhighlight lang="bqn"> {𝕊1+•Show 𝕩}0 |
||
0 |
0 |
||
1 |
1 |
||
Line 746: | Line 746: | ||
Error: Stack overflow |
Error: Stack overflow |
||
at {𝕊1+•Show 𝕩}0 |
at {𝕊1+•Show 𝕩}0 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
< |
<syntaxhighlight lang="bracmat">rec=.out$!arg&rec$(!arg+1)</syntaxhighlight> |
||
Observed recursion depths: |
Observed recursion depths: |
||
Line 757: | Line 757: | ||
=={{header|C}}== |
=={{header|C}}== |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
void recurse(unsigned int i) |
void recurse(unsigned int i) |
||
Line 769: | Line 769: | ||
recurse(0); |
recurse(0); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
Segmentation fault occurs when i is 523756. |
Segmentation fault occurs when i is 523756. |
||
Line 780: | Line 780: | ||
The following code may have some effect unexpected by the unwary: |
The following code may have some effect unexpected by the unwary: |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
char * base; |
char * base; |
||
Line 802: | Line 802: | ||
recur(); |
recur(); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
With GCC 4.5, if compiled without -O2, it segfaults quickly; if <code>gcc -O2</code>, crash never happens, because the optimizer noticed the tail recursion in recur() and turned it into a loop! |
With GCC 4.5, if compiled without -O2, it segfaults quickly; if <code>gcc -O2</code>, crash never happens, because the optimizer noticed the tail recursion in recur() and turned it into a loop! |
||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
class RecursionLimit |
class RecursionLimit |
||
{ |
{ |
||
Line 819: | Line 819: | ||
Recur(i + 1); |
Recur(i + 1); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Through debugging, the highest I achieve is 14250. |
Through debugging, the highest I achieve is 14250. |
||
Line 826: | Line 826: | ||
=={{header|C++}}== |
=={{header|C++}}== |
||
< |
<syntaxhighlight lang="cpp"> |
||
#include <iostream> |
#include <iostream> |
||
Line 839: | Line 839: | ||
recurse(0); |
recurse(0); |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
< |
<syntaxhighlight lang="clojure"> |
||
=> (def *stack* 0) |
=> (def *stack* 0) |
||
=> ((fn overflow [] ((def *stack* (inc *stack*))(overflow)))) |
=> ((fn overflow [] ((def *stack* (inc *stack*))(overflow)))) |
||
Line 848: | Line 848: | ||
=> *stack* |
=> *stack* |
||
10498 |
10498 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|COBOL}}== |
=={{header|COBOL}}== |
||
{{works with|OpenCOBOL}} |
{{works with|OpenCOBOL}} |
||
< |
<syntaxhighlight lang="cobol">identification division. |
||
program-id. recurse. |
program-id. recurse. |
||
data division. |
data division. |
||
Line 901: | Line 901: | ||
*> room for a better-than-abrupt death here. |
*> room for a better-than-abrupt death here. |
||
exit program.</ |
exit program.</syntaxhighlight> |
||
Compiled with <pre>cobc -free -x -g recurse.cbl</pre> gives, after a while, |
Compiled with <pre>cobc -free -x -g recurse.cbl</pre> gives, after a while, |
||
<pre>... |
<pre>... |
||
Line 933: | Line 933: | ||
{{works with|OpenCOBOL}} |
{{works with|OpenCOBOL}} |
||
< |
<syntaxhighlight lang="cobol"> IDENTIFICATION DIVISION. |
||
PROGRAM-ID. recurse RECURSIVE. |
PROGRAM-ID. recurse RECURSIVE. |
||
DATA DIVISION. |
DATA DIVISION. |
||
Line 957: | Line 957: | ||
EXIT PROGRAM. |
EXIT PROGRAM. |
||
END PROGRAM recurse-sub. |
END PROGRAM recurse-sub. |
||
END PROGRAM recurse. </ |
END PROGRAM recurse. </syntaxhighlight> |
||
Compiled with <pre>cobc -x -g recurse.cbl</pre> gives |
Compiled with <pre>cobc -x -g recurse.cbl</pre> gives |
||
Line 971: | Line 971: | ||
=={{header|CoffeeScript}}== |
=={{header|CoffeeScript}}== |
||
< |
<syntaxhighlight lang="coffeescript"> |
||
recurse = ( depth = 0 ) -> |
recurse = ( depth = 0 ) -> |
||
try |
try |
||
Line 979: | Line 979: | ||
console.log "Recursion depth on this system is #{ do recurse }" |
console.log "Recursion depth on this system is #{ do recurse }" |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} Example on [http://nodejs.org Node.js]: |
{{out}} Example on [http://nodejs.org Node.js]: |
||
Line 988: | Line 988: | ||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
< |
<syntaxhighlight lang="lisp"> |
||
(defun recurse () (recurse)) |
(defun recurse () (recurse)) |
||
(trace recurse) |
(trace recurse) |
||
(recurse) |
(recurse) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} This test was done with clisp under cygwin: |
{{out}} This test was done with clisp under cygwin: |
||
Line 1,008: | Line 1,008: | ||
=={{header|Crystal}}== |
=={{header|Crystal}}== |
||
< |
<syntaxhighlight lang="crystal">def recurse(counter = 0) |
||
puts counter |
puts counter |
||
recurse(counter + 1) |
recurse(counter + 1) |
||
Line 1,014: | Line 1,014: | ||
recurse() |
recurse() |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 1,023: | Line 1,023: | ||
=={{header|D}}== |
=={{header|D}}== |
||
< |
<syntaxhighlight lang="d">import std.c.stdio; |
||
void recurse(in uint i=0) { |
void recurse(in uint i=0) { |
||
Line 1,032: | Line 1,032: | ||
void main() { |
void main() { |
||
recurse(); |
recurse(); |
||
}</ |
}</syntaxhighlight> |
||
With the DMD compiler, using default compilation arguments, the stack overflows at 51_002. |
With the DMD compiler, using default compilation arguments, the stack overflows at 51_002. |
||
Line 1,041: | Line 1,041: | ||
=={{header|Dc}}== |
=={{header|Dc}}== |
||
Tail recursion is optimized into iteration by GNU dc, so I designed a not tail recursive function, summing all numbers up to n: |
Tail recursion is optimized into iteration by GNU dc, so I designed a not tail recursive function, summing all numbers up to n: |
||
< |
<syntaxhighlight lang="dc">## f(n) = (n < 1) ? n : f(n-1) + n; |
||
[q]sg |
[q]sg |
||
[dSn d1[>g 1- lfx]x Ln+]sf |
[dSn d1[>g 1- lfx]x Ln+]sf |
||
Line 1,047: | Line 1,047: | ||
65400 lhx |
65400 lhx |
||
65600 lhx</ |
65600 lhx</syntaxhighlight> |
||
With the standard Ubuntu stack size limit 8MB I get |
With the standard Ubuntu stack size limit 8MB I get |
||
{{out}} |
{{out}} |
||
Line 1,064: | Line 1,064: | ||
=={{header|Delphi}}== |
=={{header|Delphi}}== |
||
{{works with|Delphi|2010 (and probably all other versions)}} |
{{works with|Delphi|2010 (and probably all other versions)}} |
||
< |
<syntaxhighlight lang="delphi">program Project2; |
||
{$APPTYPE CONSOLE} |
{$APPTYPE CONSOLE} |
||
uses |
uses |
||
Line 1,084: | Line 1,084: | ||
Writeln('Press any key to Exit'); |
Writeln('Press any key to Exit'); |
||
Readln; |
Readln; |
||
end.</ |
end.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,093: | Line 1,093: | ||
Recursion limit is a parameter of script execution, which can be specified independently from the stack size to limit execution complexity. |
Recursion limit is a parameter of script execution, which can be specified independently from the stack size to limit execution complexity. |
||
< |
<syntaxhighlight lang="delphi">var level : Integer; |
||
procedure Recursive; |
procedure Recursive; |
||
Line 1,106: | Line 1,106: | ||
Recursive; |
Recursive; |
||
Println('Recursion Level is ' + IntToStr(level));</ |
Println('Recursion Level is ' + IntToStr(level));</syntaxhighlight> |
||
=={{header|Déjà Vu}}== |
=={{header|Déjà Vu}}== |
||
{{untested|Déjà Vu}} |
{{untested|Déjà Vu}} |
||
< |
<syntaxhighlight lang="dejavu">rec-fun n: |
||
!. n |
!. n |
||
rec-fun ++ n |
rec-fun ++ n |
||
rec-fun 0</ |
rec-fun 0</syntaxhighlight> |
||
This continues until the memory is full, so I didn't wait for it to finish. |
This continues until the memory is full, so I didn't wait for it to finish. |
||
Currently, it should to to almost 3 million levels of recursion on a machine with 1 GB free. |
Currently, it should to to almost 3 million levels of recursion on a machine with 1 GB free. |
||
Line 1,125: | Line 1,125: | ||
=={{header|EasyLang}}== |
=={{header|EasyLang}}== |
||
<lang>func recurse i . . |
<syntaxhighlight lang="text">func recurse i . . |
||
print i |
print i |
||
call recurse i + 1 |
call recurse i + 1 |
||
. |
. |
||
call recurse 0</ |
call recurse 0</syntaxhighlight> |
||
<pre> |
<pre> |
||
0 |
0 |
||
Line 1,144: | Line 1,144: | ||
=={{header|Emacs Lisp}}== |
=={{header|Emacs Lisp}}== |
||
< |
<syntaxhighlight lang="lisp">(defun my-recurse (n) |
||
(my-recurse (1+ n))) |
(my-recurse (1+ n))) |
||
(my-recurse 1) |
(my-recurse 1) |
||
=> |
=> |
||
enters debugger at (my-recurse 595), |
enters debugger at (my-recurse 595), |
||
per the default max-lisp-eval-depth 600 in Emacs 24.1</ |
per the default max-lisp-eval-depth 600 in Emacs 24.1</syntaxhighlight> |
||
Variable <code>max-lisp-eval-depth</code>[http://www.gnu.org/software/emacs/manual/html_node/elisp/Eval.html#index-max_002dlisp_002deval_002ddepth-539] is the maximum depth of function calls and variable <code>max-specpdl-size</code>[http://www.gnu.org/software/emacs/manual/html_node/elisp/Local-Variables.html#index-max_002dspecpdl_002dsize-614] is the maximum depth of nested <code>let</code> bindings. A function call is a <code>let</code> of the parameters, even if there's no parameters, and so counts towards <code>max-specpdl-size</code> as well as <code>max-lisp-eval-depth</code>. |
Variable <code>max-lisp-eval-depth</code>[http://www.gnu.org/software/emacs/manual/html_node/elisp/Eval.html#index-max_002dlisp_002deval_002ddepth-539] is the maximum depth of function calls and variable <code>max-specpdl-size</code>[http://www.gnu.org/software/emacs/manual/html_node/elisp/Local-Variables.html#index-max_002dspecpdl_002dsize-614] is the maximum depth of nested <code>let</code> bindings. A function call is a <code>let</code> of the parameters, even if there's no parameters, and so counts towards <code>max-specpdl-size</code> as well as <code>max-lisp-eval-depth</code>. |
||
Line 1,161: | Line 1,161: | ||
A tail-recursive function will run indefinitely without problems (the integer will overflow, though). |
A tail-recursive function will run indefinitely without problems (the integer will overflow, though). |
||
< |
<syntaxhighlight lang="fsharp">let rec recurse n = |
||
recurse (n+1) |
recurse (n+1) |
||
recurse 0</ |
recurse 0</syntaxhighlight> |
||
The non-tail recursive function of the following example crashed with a <code>StackOverflowException</code> after 39958 recursive calls: |
The non-tail recursive function of the following example crashed with a <code>StackOverflowException</code> after 39958 recursive calls: |
||
< |
<syntaxhighlight lang="fsharp">let rec recurse n = |
||
printfn "%d" n |
printfn "%d" n |
||
1 + recurse (n+1) |
1 + recurse (n+1) |
||
recurse 0 |> ignore</ |
recurse 0 |> ignore</syntaxhighlight> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
Factor is tail-call optimized, so the following example will run without issue. In fact, Factor's iterative combinators such as <code>map</code>, <code>each</code>, and <code>times</code> are written in terms of tail recursion. |
Factor is tail-call optimized, so the following example will run without issue. In fact, Factor's iterative combinators such as <code>map</code>, <code>each</code>, and <code>times</code> are written in terms of tail recursion. |
||
< |
<syntaxhighlight lang="factor">: recurse ( n -- n ) 1 + recurse ; |
||
0 recurse</ |
0 recurse</syntaxhighlight> |
||
The following non-tail recursive word caused a call stack overflow error after 65518 recursive calls in the listener. |
The following non-tail recursive word caused a call stack overflow error after 65518 recursive calls in the listener. |
||
< |
<syntaxhighlight lang="factor">SYMBOL: depth |
||
: fn ( n -- n ) depth inc 1 + fn 1 + ; |
: fn ( n -- n ) depth inc 1 + fn 1 + ; |
||
[ 0 fn ] try |
[ 0 fn ] try |
||
depth get "Recursion depth on this system is %d.\n" printf</ |
depth get "Recursion depth on this system is %d.\n" printf</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,195: | Line 1,195: | ||
=={{header|Fermat}}== |
=={{header|Fermat}}== |
||
< |
<syntaxhighlight lang="fermat"> |
||
Func Sisyphus(n)=!!n;Sisyphus(n+1). |
Func Sisyphus(n)=!!n;Sisyphus(n+1). |
||
Sisyphus(0) |
Sisyphus(0) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,211: | Line 1,211: | ||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
< |
<syntaxhighlight lang="forth">: munge ( n -- n' ) 1+ recurse ; |
||
: test 0 ['] munge catch if ." Recursion limit at depth " . then ; |
: test 0 ['] munge catch if ." Recursion limit at depth " . then ; |
||
test \ Default gforth: Recursion limit at depth 3817</ |
test \ Default gforth: Recursion limit at depth 3817</syntaxhighlight> |
||
Or you can just ask the system: |
Or you can just ask the system: |
||
< |
<syntaxhighlight lang="forth">s" return-stack-cells" environment? ( 0 | potential-depth-of-return-stack -1 )</syntaxhighlight> |
||
Full TCO is problematic, but a properly tail-recursive call is easy to add to any Forth. For example, in SwiftForth: |
Full TCO is problematic, but a properly tail-recursive call is easy to add to any Forth. For example, in SwiftForth: |
||
< |
<syntaxhighlight lang="forth">: recur; [ last 2 cells + literal ] @ +bal postpone again ; immediate |
||
: test dup if 1+ recur; then drop ." I gave up finding a limit!" ; |
: test dup if 1+ recur; then drop ." I gave up finding a limit!" ; |
||
1 test</ |
1 test</syntaxhighlight> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
< |
<syntaxhighlight lang="fortran">program recursion_depth |
||
implicit none |
implicit none |
||
Line 1,248: | Line 1,248: | ||
end subroutine recurse |
end subroutine recurse |
||
end program recursion_depth</ |
end program recursion_depth</syntaxhighlight> |
||
{{out}} (snipped): |
{{out}} (snipped): |
||
<pre>208914 |
<pre>208914 |
||
Line 1,264: | Line 1,264: | ||
=={{header|GAP}}== |
=={{header|GAP}}== |
||
The limit is around 5000 : |
The limit is around 5000 : |
||
< |
<syntaxhighlight lang="gap">f := function(n) |
||
return f(n+1); |
return f(n+1); |
||
end; |
end; |
||
Line 1,280: | Line 1,280: | ||
# quit "brk mode" and return to GAP |
# quit "brk mode" and return to GAP |
||
quit;</ |
quit;</syntaxhighlight> |
||
This is the default GAP recursion trap, see [http://www.gap-system.org/Manuals/doc/htm/ref/CHAP007.htm#SECT010 reference manual, section 7.10]. It enters "brk mode" after multiples of 5000 recursions levels. On can change this interval : |
This is the default GAP recursion trap, see [http://www.gap-system.org/Manuals/doc/htm/ref/CHAP007.htm#SECT010 reference manual, section 7.10]. It enters "brk mode" after multiples of 5000 recursions levels. On can change this interval : |
||
< |
<syntaxhighlight lang="gap">SetRecursionTrapInterval(100000); |
||
# No limit (may crash GAP if recursion is not controlled) : |
# No limit (may crash GAP if recursion is not controlled) : |
||
SetRecursionTrapInterval(0);</ |
SetRecursionTrapInterval(0);</syntaxhighlight> |
||
=={{header|gnuplot}}== |
=={{header|gnuplot}}== |
||
< |
<syntaxhighlight lang="gnuplot"># Put this in a file foo.gnuplot and run as |
||
# gnuplot foo.gnuplot |
# gnuplot foo.gnuplot |
||
Line 1,297: | Line 1,297: | ||
print "try recurse ", try |
print "try recurse ", try |
||
print recurse(try) |
print recurse(try) |
||
reread</ |
reread</syntaxhighlight> |
||
Gnuplot 4.6 has a builtin <code>STACK_DEPTH</code> limit of 250, giving |
Gnuplot 4.6 has a builtin <code>STACK_DEPTH</code> limit of 250, giving |
||
Line 1,315: | Line 1,315: | ||
The default can be changed by [https://golang.org/pkg/runtime/debug#SetMaxStack <code>SetMaxStack</code>] in the <code>runtime/debug</code> package. It is documented as "useful mainly for limiting the damage done by goroutines that enter an infinite recursion." |
The default can be changed by [https://golang.org/pkg/runtime/debug#SetMaxStack <code>SetMaxStack</code>] in the <code>runtime/debug</code> package. It is documented as "useful mainly for limiting the damage done by goroutines that enter an infinite recursion." |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 1,337: | Line 1,337: | ||
} |
} |
||
r(l + 1) |
r(l + 1) |
||
}</ |
}</syntaxhighlight> |
||
Run without arguments on a 64-bit system: |
Run without arguments on a 64-bit system: |
||
Line 1,455: | Line 1,455: | ||
In Gri 2.12.23 the total depth of command calls is limited to an internal array size <code>cmd_being_done_LEN</code> which is 100. There's no protection or error check against exceeding this, so the following code segfaults shortly after 100, |
In Gri 2.12.23 the total depth of command calls is limited to an internal array size <code>cmd_being_done_LEN</code> which is 100. There's no protection or error check against exceeding this, so the following code segfaults shortly after 100, |
||
< |
<syntaxhighlight lang="gri">`Recurse' |
||
{ |
{ |
||
show .depth. |
show .depth. |
||
Line 1,462: | Line 1,462: | ||
} |
} |
||
.depth. = 1 |
.depth. = 1 |
||
Recurse</ |
Recurse</syntaxhighlight> |
||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
{{Trans|Java}} |
{{Trans|Java}} |
||
Solution: |
Solution: |
||
< |
<syntaxhighlight lang="groovy">def recurse; |
||
recurse = { |
recurse = { |
||
try { |
try { |
||
Line 1,476: | Line 1,476: | ||
} |
} |
||
recurse(0)</ |
recurse(0)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,482: | Line 1,482: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang="haskell">import Debug.Trace (trace) |
||
recurse :: Int -> Int |
recurse :: Int -> Int |
||
Line 1,488: | Line 1,488: | ||
main :: IO () |
main :: IO () |
||
main = print $ recurse 1</ |
main = print $ recurse 1</syntaxhighlight> |
||
Or point-free: |
Or point-free: |
||
< |
<syntaxhighlight lang="haskell">import Debug.Trace (trace) |
||
import Data.Function (fix) |
import Data.Function (fix) |
||
Line 1,498: | Line 1,498: | ||
main :: IO () |
main :: IO () |
||
main = print $ recurse 1</ |
main = print $ recurse 1</syntaxhighlight> |
||
Or, more practically, testing up to a given depth: |
Or, more practically, testing up to a given depth: |
||
< |
<syntaxhighlight lang="haskell">import Debug.Trace (trace) |
||
testToDepth :: Int -> Int -> Int |
testToDepth :: Int -> Int -> Int |
||
Line 1,511: | Line 1,511: | ||
main :: IO () |
main :: IO () |
||
main = print $ testToDepth 1000000 1</ |
main = print $ testToDepth 1000000 1</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>... |
<pre>... |
||
Line 1,530: | Line 1,530: | ||
=={{header|hexiscript}}== |
=={{header|hexiscript}}== |
||
< |
<syntaxhighlight lang="hexiscript">fun rec n |
||
println n |
println n |
||
rec (n + 1) |
rec (n + 1) |
||
endfun |
endfun |
||
rec 1</ |
rec 1</syntaxhighlight> |
||
=={{header|HolyC}}== |
=={{header|HolyC}}== |
||
The point at which a stack overflow occurs varies depending upon how many parameters passed onto the stack. Running the code from within the editor on a fresh boot of TempleOS will cause a stack overflow when <code>i</code> is larger than ~8100. |
The point at which a stack overflow occurs varies depending upon how many parameters passed onto the stack. Running the code from within the editor on a fresh boot of TempleOS will cause a stack overflow when <code>i</code> is larger than ~8100. |
||
< |
<syntaxhighlight lang="holyc">U0 Recurse(U64 i) { |
||
Print("%d\n", i); |
Print("%d\n", i); |
||
Recurse(i + 1); |
Recurse(i + 1); |
||
} |
} |
||
Recurse(0);</ |
Recurse(0);</syntaxhighlight> |
||
=={{header|i}}== |
=={{header|i}}== |
||
< |
<syntaxhighlight lang="i">function test(counter) { |
||
print(counter) |
print(counter) |
||
test(counter+1) |
test(counter+1) |
||
Line 1,555: | Line 1,555: | ||
software { |
software { |
||
test(0) |
test(0) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Icon}} and {{header|Unicon}}== |
=={{header|Icon}} and {{header|Unicon}}== |
||
< |
<syntaxhighlight lang="icon">procedure main() |
||
envar := "MSTKSIZE" |
envar := "MSTKSIZE" |
||
write(&errout,"Program to test recursion depth - dependant on the environment variable ",envar," = ",\getenv(envar)|&null) |
write(&errout,"Program to test recursion depth - dependant on the environment variable ",envar," = ",\getenv(envar)|&null) |
||
Line 1,569: | Line 1,569: | ||
write( d +:= 1) |
write( d +:= 1) |
||
deepdive() |
deepdive() |
||
end</ |
end</syntaxhighlight> |
||
Note: The stack size environment variable defaults to about 50000 words. This terminates after approximately 3500 recursions (Windows). The interpreter should terminate with a 301 error, but currently this does not work. |
Note: The stack size environment variable defaults to about 50000 words. This terminates after approximately 3500 recursions (Windows). The interpreter should terminate with a 301 error, but currently this does not work. |
||
=={{header|Inform 7}}== |
=={{header|Inform 7}}== |
||
< |
<syntaxhighlight lang="inform7">Home is a room. |
||
When play begins: recurse 0. |
When play begins: recurse 0. |
||
Line 1,579: | Line 1,579: | ||
To recurse (N - number): |
To recurse (N - number): |
||
say "[N]."; |
say "[N]."; |
||
recurse N + 1.</ |
recurse N + 1.</syntaxhighlight> |
||
Using the interpreters built into Windows build 6F95, a stack overflow occurs after 6529 recursions on the Z-machine or 2030 recursions on Glulx. |
Using the interpreters built into Windows build 6F95, a stack overflow occurs after 6529 recursions on the Z-machine or 2030 recursions on Glulx. |
||
Line 1,588: | Line 1,588: | ||
Note also that task assumes that all stack frames must be the same size, which is probably not the case. |
Note also that task assumes that all stack frames must be the same size, which is probably not the case. |
||
< |
<syntaxhighlight lang="j">(recur=: verb def 'recur smoutput N=:N+1')N=:0</syntaxhighlight> |
||
This above gives a stack depth of 9998 on one machine. |
This above gives a stack depth of 9998 on one machine. |
||
Line 1,595: | Line 1,595: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
<syntaxhighlight lang="java"> |
|||
<lang Java> |
|||
public class RecursionTest { |
public class RecursionTest { |
||
Line 1,610: | Line 1,610: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 1,620: | Line 1,620: | ||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
< |
<syntaxhighlight lang="javascript"> |
||
function recurse(depth) |
function recurse(depth) |
||
{ |
{ |
||
Line 1,634: | Line 1,634: | ||
var maxRecursion = recurse(1); |
var maxRecursion = recurse(1); |
||
document.write("Recursion depth on this system is " + maxRecursion);</ |
document.write("Recursion depth on this system is " + maxRecursion);</syntaxhighlight> |
||
{{out}} (Chrome): |
{{out}} (Chrome): |
||
Line 1,651: | Line 1,651: | ||
'''Arity-0 Function''' |
'''Arity-0 Function''' |
||
< |
<syntaxhighlight lang="jq">def zero_arity: |
||
if (. % 1000000 == 0) then . else empty end, ((.+1)| zero_arity); |
if (. % 1000000 == 0) then . else empty end, ((.+1)| zero_arity); |
||
1|zero_arity</ |
1|zero_arity</syntaxhighlight> |
||
'''Arity-1 Function''' |
'''Arity-1 Function''' |
||
< |
<syntaxhighlight lang="jq">def with_arity(n): |
||
if (n % 1000 == 0) then n else empty end, with_arity(n+1); |
if (n % 1000 == 0) then n else empty end, with_arity(n+1); |
||
with_arity(1)</ |
with_arity(1)</syntaxhighlight> |
||
'''Results using jq 1.4''' |
'''Results using jq 1.4''' |
||
<syntaxhighlight lang="sh"> |
|||
<lang sh> |
|||
# Arity 0 - without TCO: |
# Arity 0 - without TCO: |
||
... |
... |
||
Line 1,680: | Line 1,680: | ||
242000 # 50.0 MB (5h:14m) |
242000 # 50.0 MB (5h:14m) |
||
# [job cancelled manually after over 5 hours] |
# [job cancelled manually after over 5 hours] |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Results using jq with TCO''' |
'''Results using jq with TCO''' |
||
The arity-0 test was stopped after the recursive function had been called 100,000,000 (10^8) times. The memory required did not grow beyond 360 KB (sic). |
The arity-0 test was stopped after the recursive function had been called 100,000,000 (10^8) times. The memory required did not grow beyond 360 KB (sic). |
||
<syntaxhighlight lang="sh"> |
|||
<lang sh> |
|||
$ time jq -n -f Find_limit_of_recursions.jq |
$ time jq -n -f Find_limit_of_recursions.jq |
||
... |
... |
||
Line 1,693: | Line 1,693: | ||
user 2m0.534s |
user 2m0.534s |
||
sys 0m0.329s |
sys 0m0.329s |
||
</syntaxhighlight> |
|||
</lang> |
|||
The arity-1 test process was terminated simply because it had become too slow; at that point it had only consumed about 74.6K MB. |
The arity-1 test process was terminated simply because it had become too slow; at that point it had only consumed about 74.6K MB. |
||
<syntaxhighlight lang="sh"> |
|||
<lang sh> |
|||
... |
... |
||
56000 # 9.9MB |
56000 # 9.9MB |
||
Line 1,710: | Line 1,710: | ||
406000 # 74.6 MB (8h:50m) |
406000 # 74.6 MB (8h:50m) |
||
412000 # 74.6 MB (9h:05m) |
412000 # 74.6 MB (9h:05m) |
||
# [job cancelled manually after over 9 hours]</ |
# [job cancelled manually after over 9 hours]</syntaxhighlight> |
||
'''Discussion''' |
'''Discussion''' |
||
Line 1,725: | Line 1,725: | ||
'''Clean''' |
'''Clean''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function divedivedive(d::Int) |
function divedivedive(d::Int) |
||
try |
try |
||
Line 1,733: | Line 1,733: | ||
end |
end |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Dirty''' |
'''Dirty''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
function divedivedive() |
function divedivedive() |
||
global depth |
global depth |
||
Line 1,741: | Line 1,741: | ||
divedivedive() |
divedivedive() |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Main''' |
'''Main''' |
||
<syntaxhighlight lang="julia"> |
|||
<lang Julia> |
|||
depth = divedivedive(0) |
depth = divedivedive(0) |
||
println("A clean dive reaches a depth of ", depth, ".") |
println("A clean dive reaches a depth of ", depth, ".") |
||
Line 1,752: | Line 1,752: | ||
end |
end |
||
println("A dirty dive reaches a depth of ", depth, ".") |
println("A dirty dive reaches a depth of ", depth, ".") |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 1,764: | Line 1,764: | ||
One might have expected that the result would be the same (or only vary over a small range) for a given configuration but in fact the results are all over the place - running the program a number of times I obtained figures as high as 26400 and as low as 9099! I have no idea why. |
One might have expected that the result would be the same (or only vary over a small range) for a given configuration but in fact the results are all over the place - running the program a number of times I obtained figures as high as 26400 and as low as 9099! I have no idea why. |
||
< |
<syntaxhighlight lang="scala">// version 1.1.2 |
||
fun recurse(i: Int) { |
fun recurse(i: Int) { |
||
Line 1,775: | Line 1,775: | ||
} |
} |
||
fun main(args: Array<String>) = recurse(0)</ |
fun main(args: Array<String>) = recurse(0)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,784: | Line 1,784: | ||
=={{header|Liberty BASIC}}== |
=={{header|Liberty BASIC}}== |
||
Checks for the case of gosub & for proper subroutine. |
Checks for the case of gosub & for proper subroutine. |
||
<syntaxhighlight lang="lb"> |
|||
<lang lb> |
|||
'subroutine recursion limit- end up on 475000 |
'subroutine recursion limit- end up on 475000 |
||
Line 1,793: | Line 1,793: | ||
call test n+1 |
call test n+1 |
||
end sub |
end sub |
||
</ |
</syntaxhighlight> |
||
<syntaxhighlight lang="lb"> |
|||
<lang lb> |
|||
'gosub recursion limit- end up on 5767000 |
'gosub recursion limit- end up on 5767000 |
||
[test] |
[test] |
||
Line 1,801: | Line 1,801: | ||
if n mod 1000 = 0 then locate 1,1: print n |
if n mod 1000 = 0 then locate 1,1: print n |
||
gosub [test] |
gosub [test] |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|LIL}}== |
=={{header|LIL}}== |
||
lil.c allows an optional build time value to set a limit on recursion: |
lil.c allows an optional build time value to set a limit on recursion: |
||
< |
<syntaxhighlight lang="c">/* Enable limiting recursive calls to lil_parse - this can be used to avoid call stack |
||
* overflows and is also useful when running through an automated fuzzer like AFL */ |
* overflows and is also useful when running through an automated fuzzer like AFL */ |
||
/*#define LIL_ENABLE_RECLIMIT 10000*/</ |
/*#define LIL_ENABLE_RECLIMIT 10000*/</syntaxhighlight> |
||
Otherwise, it is a race to run out of stack: |
Otherwise, it is a race to run out of stack: |
||
Line 1,828: | Line 1,828: | ||
Like Scheme, Logo guarantees tail call elimination, so recursion is effectively unbounded. You can catch a user interrupt though to see how deep you could go. |
Like Scheme, Logo guarantees tail call elimination, so recursion is effectively unbounded. You can catch a user interrupt though to see how deep you could go. |
||
< |
<syntaxhighlight lang="logo">make "depth 0 |
||
to recurse |
to recurse |
||
Line 1,838: | Line 1,838: | ||
; hit control-C after waiting a while |
; hit control-C after waiting a while |
||
print error ; 16 Stopping... recurse [make "depth :depth + 1] |
print error ; 16 Stopping... recurse [make "depth :depth + 1] |
||
(print [Depth reached:] :depth) ; some arbitrarily large number</ |
(print [Depth reached:] :depth) ; some arbitrarily large number</syntaxhighlight> |
||
=={{header|LSL}}== |
=={{header|LSL}}== |
||
Line 1,846: | Line 1,846: | ||
To test it yourself; rez a box on the ground, and add the following as a New Script. |
To test it yourself; rez a box on the ground, and add the following as a New Script. |
||
< |
<syntaxhighlight lang="lsl">integer iLimit_of_Recursion = 0; |
||
Find_Limit_of_Recursion(integer x) { |
Find_Limit_of_Recursion(integer x) { |
||
llOwnerSay("x="+(string)x); |
llOwnerSay("x="+(string)x); |
||
Line 1,858: | Line 1,858: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,875: | Line 1,875: | ||
Lua (version 5.3) support proper tail call, if the recursion is proper tail call there is no limit. |
Lua (version 5.3) support proper tail call, if the recursion is proper tail call there is no limit. |
||
Otherwise, it is limited by stack size set by the implementation. |
Otherwise, it is limited by stack size set by the implementation. |
||
<syntaxhighlight lang="lua"> |
|||
<lang Lua> |
|||
local c = 0 |
local c = 0 |
||
function Tail(proper) |
function Tail(proper) |
||
Line 1,891: | Line 1,891: | ||
ok,check = pcall(Tail,false) |
ok,check = pcall(Tail,false) |
||
print(c, ok, check) |
print(c, ok, check) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,900: | Line 1,900: | ||
=={{header|M2000 Interpreter}}== |
=={{header|M2000 Interpreter}}== |
||
===Modules & Functions=== |
===Modules & Functions=== |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module checkit { |
Module checkit { |
||
Global z |
Global z |
||
Line 1,949: | Line 1,949: | ||
} |
} |
||
Checkit |
Checkit |
||
</syntaxhighlight> |
|||
</lang> |
|||
In Wine give these: |
In Wine give these: |
||
<pre> |
<pre> |
||
Line 1,969: | Line 1,969: | ||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module Checkit { |
Module Checkit { |
||
\\ recursion for subs controled by a value |
\\ recursion for subs controled by a value |
||
Line 1,997: | Line 1,997: | ||
} |
} |
||
Checkit |
Checkit |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
The variable $RecursionLimit can be read for its current value or set to different values. eg |
The variable $RecursionLimit can be read for its current value or set to different values. eg |
||
<lang>$RecursionLimit=10^6</ |
<syntaxhighlight lang="text">$RecursionLimit=10^6</syntaxhighlight> |
||
Would set the recursion limit to one million. |
Would set the recursion limit to one million. |
||
Line 2,008: | Line 2,008: | ||
Sample Usage: |
Sample Usage: |
||
< |
<syntaxhighlight lang="matlab">>> get(0,'RecursionLimit') |
||
ans = |
ans = |
||
Line 2,019: | Line 2,019: | ||
ans = |
ans = |
||
2500</ |
2500</syntaxhighlight> |
||
=={{header|Maxima}}== |
=={{header|Maxima}}== |
||
< |
<syntaxhighlight lang="maxima">f(p) := f(n: p + 1)$ |
||
f(0); |
f(0); |
||
Maxima encountered a Lisp error: |
Maxima encountered a Lisp error: |
||
Line 2,030: | Line 2,030: | ||
n; |
n; |
||
406</ |
406</syntaxhighlight> |
||
=={{header|МК-61/52}}== |
=={{header|МК-61/52}}== |
||
<lang>П2 ПП 05 ИП1 С/П |
<syntaxhighlight lang="text">П2 ПП 05 ИП1 С/П |
||
ИП0 ИП2 - x<0 20 ИП0 1 + П0 ПП 05 |
ИП0 ИП2 - x<0 20 ИП0 1 + П0 ПП 05 |
||
ИП1 1 + П1 В/О</ |
ИП1 1 + П1 В/О</syntaxhighlight> |
||
=={{header|Modula-2}}== |
=={{header|Modula-2}}== |
||
< |
<syntaxhighlight lang="modula2">MODULE recur; |
||
IMPORT InOut; |
IMPORT InOut; |
||
Line 2,051: | Line 2,051: | ||
BEGIN |
BEGIN |
||
recursion (0) |
recursion (0) |
||
END recur.</ |
END recur.</syntaxhighlight> |
||
Producing this: |
Producing this: |
||
<syntaxhighlight lang="modula-2"> |
|||
<lang Modula-2> |
|||
jan@Beryllium:~/modula/rosetta$ recur >testfile |
jan@Beryllium:~/modula/rosetta$ recur >testfile |
||
Segmentation fault |
Segmentation fault |
||
Line 2,061: | Line 2,061: | ||
-rw-r--r-- 1 jan users 523264 2011-05-20 00:26 testfile |
-rw-r--r-- 1 jan users 523264 2011-05-20 00:26 testfile |
||
jan@Beryllium:~/modula/rosetta$ wc testfile |
jan@Beryllium:~/modula/rosetta$ wc testfile |
||
0 1 523264 testfile</ |
0 1 523264 testfile</syntaxhighlight> |
||
So the recursion depth is just over half a million. |
So the recursion depth is just over half a million. |
||
=={{header|MUMPS}}== |
=={{header|MUMPS}}== |
||
< |
<syntaxhighlight lang="mumps">RECURSE |
||
IF $DATA(DEPTH)=1 SET DEPTH=1+DEPTH |
IF $DATA(DEPTH)=1 SET DEPTH=1+DEPTH |
||
IF $DATA(DEPTH)=0 SET DEPTH=1 |
IF $DATA(DEPTH)=0 SET DEPTH=1 |
||
WRITE !,DEPTH_" levels down" |
WRITE !,DEPTH_" levels down" |
||
DO RECURSE |
DO RECURSE |
||
QUIT</ |
QUIT</syntaxhighlight> |
||
End of the run ...<pre> |
End of the run ...<pre> |
||
1918 levels down |
1918 levels down |
||
Line 2,083: | Line 2,083: | ||
=={{header|Nanoquery}}== |
=={{header|Nanoquery}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="nanoquery">def recurse(counter) |
||
println counter |
println counter |
||
counter += 1 |
counter += 1 |
||
Line 2,089: | Line 2,089: | ||
end |
end |
||
recurse(1)</ |
recurse(1)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>1 |
<pre>1 |
||
Line 2,101: | Line 2,101: | ||
=={{header|Neko}}== |
=={{header|Neko}}== |
||
<syntaxhighlight lang="actionscript">/** |
|||
<lang ActionScript>/** |
|||
Recursion limit, in Neko |
Recursion limit, in Neko |
||
*/ |
*/ |
||
Line 2,128: | Line 2,128: | ||
try $print("Recurse: ", recurse(0), " sum: ", sum, "\n") |
try $print("Recurse: ", recurse(0), " sum: ", sum, "\n") |
||
catch with $print("recurse limit exception: ", counter, " ", with, "\n")</ |
catch with $print("recurse limit exception: ", counter, " ", with, "\n")</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,138: | Line 2,138: | ||
=={{header|NetRexx}}== |
=={{header|NetRexx}}== |
||
Like Java, NetRexx memory allocation is managed by the JVM under which it is run. The following sample presents runtime memory allocations then begins the recursion run. |
Like Java, NetRexx memory allocation is managed by the JVM under which it is run. The following sample presents runtime memory allocations then begins the recursion run. |
||
< |
<syntaxhighlight lang="netrexx">/* NetRexx */ |
||
options replace format comments java crossref symbols binary |
options replace format comments java crossref symbols binary |
||
Line 2,175: | Line 2,175: | ||
say |
say |
||
return |
return |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,188: | Line 2,188: | ||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
< |
<syntaxhighlight lang="nim">proc recurse(i: int): int = |
||
echo i |
echo i |
||
recurse(i+1) |
recurse(i+1) |
||
echo recurse(0)</ |
echo recurse(0)</syntaxhighlight> |
||
Compiled without optimizations (debug build), the program stops with the following message: |
Compiled without optimizations (debug build), the program stops with the following message: |
||
<pre>Error: call depth limit reached in a debug build (2000 function calls). You can change it with -d:nimCallDepthLimit=<int> but really try to avoid deep recursions instead.</pre> |
<pre>Error: call depth limit reached in a debug build (2000 function calls). You can change it with -d:nimCallDepthLimit=<int> but really try to avoid deep recursions instead.</pre> |
||
Line 2,209: | Line 2,209: | ||
If the recursion is not a tail one, the execution is stopped with the message |
If the recursion is not a tail one, the execution is stopped with the message |
||
"Stack overflow": |
"Stack overflow": |
||
< |
<syntaxhighlight lang="ocaml"># let last = ref 0 ;; |
||
val last : int ref = {contents = 0} |
val last : int ref = {contents = 0} |
||
# let rec f i = |
# let rec f i = |
||
Line 2,219: | Line 2,219: | ||
stack overflow during evaluation (looping recursion?). |
stack overflow during evaluation (looping recursion?). |
||
# !last ;; |
# !last ;; |
||
- : int = 262067</ |
- : int = 262067</syntaxhighlight> |
||
here we see that the function call stack size is 262067. |
here we see that the function call stack size is 262067. |
||
< |
<syntaxhighlight lang="ocaml">(* One can build a function from the idea above, catching the exception *) |
||
let rec_limit () = |
let rec_limit () = |
||
Line 2,239: | Line 2,239: | ||
(* Since with have eaten some stack with this function, the result is slightly lower. |
(* Since with have eaten some stack with this function, the result is slightly lower. |
||
But now it may be used inside any function to get the available stack space *)</ |
But now it may be used inside any function to get the available stack space *)</syntaxhighlight> |
||
=={{header|Oforth}}== |
=={{header|Oforth}}== |
||
Line 2,245: | Line 2,245: | ||
Limit found is 173510 on Windows system. Should be more on Linux system. |
Limit found is 173510 on Windows system. Should be more on Linux system. |
||
< |
<syntaxhighlight lang="oforth">: limit 1+ dup . limit ; |
||
0 limit</ |
0 limit</syntaxhighlight> |
||
=={{header|ooRexx}}== |
=={{header|ooRexx}}== |
||
Line 2,273: | Line 2,273: | ||
Oz supports an unbounded number of tail calls. So the following code can run forever with constant memory use (although the space used to represent <code>Number</code> will slowly increase): |
Oz supports an unbounded number of tail calls. So the following code can run forever with constant memory use (although the space used to represent <code>Number</code> will slowly increase): |
||
< |
<syntaxhighlight lang="oz">declare |
||
proc {Recurse Number} |
proc {Recurse Number} |
||
{Show Number} |
{Show Number} |
||
Line 2,279: | Line 2,279: | ||
end |
end |
||
in |
in |
||
{Recurse 1}</ |
{Recurse 1}</syntaxhighlight> |
||
With non-tail recursive functions, the number of recursions is only limited by the available memory. |
With non-tail recursive functions, the number of recursions is only limited by the available memory. |
||
Line 2,285: | Line 2,285: | ||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
As per "Recursive functions" in the Pari/GP users's manual. |
As per "Recursive functions" in the Pari/GP users's manual. |
||
< |
<syntaxhighlight lang="parigp">dive(n) = dive(n+1) |
||
dive(0)</ |
dive(0)</syntaxhighlight> |
||
The limit is the underlying C language stack. Deep recursion is detected before the stack is completely exhausted (by checking <code>RLIMIT_STACK</code>) so a <code>gp</code> level error is thrown instead of a segfault. |
The limit is the underlying C language stack. Deep recursion is detected before the stack is completely exhausted (by checking <code>RLIMIT_STACK</code>) so a <code>gp</code> level error is thrown instead of a segfault. |
||
Line 2,296: | Line 2,296: | ||
Maximum recursion depth is memory dependent. |
Maximum recursion depth is memory dependent. |
||
< |
<syntaxhighlight lang="perl">my $x = 0; |
||
recurse($x); |
recurse($x); |
||
Line 2,302: | Line 2,302: | ||
print ++$x,"\n"; |
print ++$x,"\n"; |
||
recurse($x); |
recurse($x); |
||
}</ |
}</syntaxhighlight> |
||
Line 2,318: | Line 2,318: | ||
On 32-bit the limit is an impressive 31 million. I have seen this hit 43 million on 64-bit, but it then forced a hard reboot.<br> |
On 32-bit the limit is an impressive 31 million. I have seen this hit 43 million on 64-bit, but it then forced a hard reboot.<br> |
||
Those limits will obviously be significantly smaller for routines with more parameters, local variables, and temps. |
Those limits will obviously be significantly smaller for routines with more parameters, local variables, and temps. |
||
<!--< |
<!--<syntaxhighlight lang="phix">--> |
||
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time<span style="color: #0000FF;">(<span style="color: #0000FF;">)<span style="color: #0000FF;">+<span style="color: #000000;">1</span> |
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time<span style="color: #0000FF;">(<span style="color: #0000FF;">)<span style="color: #0000FF;">+<span style="color: #000000;">1</span> |
||
Line 2,336: | Line 2,336: | ||
<span style="color: #000000;">recurse<span style="color: #0000FF;">(<span style="color: #0000FF;">) |
<span style="color: #000000;">recurse<span style="color: #0000FF;">(<span style="color: #0000FF;">) |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out|output|text= 32 bit}} |
{{out|output|text= 32 bit}} |
||
<pre> |
<pre> |
||
Line 2,380: | Line 2,380: | ||
=== saner === |
=== saner === |
||
The following much more safely merely tests it can reach 20,000,000, plus however far it gets in the last whole-second |
The following much more safely merely tests it can reach 20,000,000, plus however far it gets in the last whole-second |
||
<!--< |
<!--<syntaxhighlight lang="phix">--> |
||
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time<span style="color: #0000FF;">(<span style="color: #0000FF;">)<span style="color: #0000FF;">+<span style="color: #000000;">1</span> |
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time<span style="color: #0000FF;">(<span style="color: #0000FF;">)<span style="color: #0000FF;">+<span style="color: #000000;">1</span> |
||
Line 2,405: | Line 2,405: | ||
<span style="color: #000000;">recurse<span style="color: #0000FF;">(<span style="color: #0000FF;">) |
<span style="color: #000000;">recurse<span style="color: #0000FF;">(<span style="color: #0000FF;">) |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,418: | Line 2,418: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php"><?php |
||
function a() { |
function a() { |
||
static $i = 0; |
static $i = 0; |
||
Line 2,424: | Line 2,424: | ||
a(); |
a(); |
||
} |
} |
||
a();</ |
a();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,476: | Line 2,476: | ||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
<syntaxhighlight lang="pl/i"> |
|||
<lang PL/I> |
|||
recurs: proc options (main) reorder; |
recurs: proc options (main) reorder; |
||
dcl sysprint file; |
dcl sysprint file; |
||
Line 2,493: | Line 2,493: | ||
call recursive(); |
call recursive(); |
||
end recurs; |
end recurs; |
||
</syntaxhighlight> |
|||
</lang> |
|||
Result (abbreviated): |
Result (abbreviated): |
||
Line 2,518: | Line 2,518: | ||
we send the results to a pipeline, we can process the earlier results before handling the |
we send the results to a pipeline, we can process the earlier results before handling the |
||
exception. |
exception. |
||
<syntaxhighlight lang="powershell"> |
|||
<lang PowerShell> |
|||
function TestDepth ( $N ) |
function TestDepth ( $N ) |
||
{ |
{ |
||
Line 2,534: | Line 2,534: | ||
} |
} |
||
"Last level before error: " + $Depth |
"Last level before error: " + $Depth |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,547: | Line 2,547: | ||
In addition to the stack size the recursion limit for procedures is further limited by the procedure's parameters and local variables which are also stored on the same stack. |
In addition to the stack size the recursion limit for procedures is further limited by the procedure's parameters and local variables which are also stored on the same stack. |
||
< |
<syntaxhighlight lang="purebasic">Procedure Recur(n) |
||
PrintN(str(n)) |
PrintN(str(n)) |
||
Recur(n+1) |
Recur(n+1) |
||
EndProcedure |
EndProcedure |
||
Recur(1)</ |
Recur(1)</syntaxhighlight> |
||
Stack overflow after 86317 recursions on x86 Vista. |
Stack overflow after 86317 recursions on x86 Vista. |
||
===Classic=== |
===Classic=== |
||
<syntaxhighlight lang="purebasic">rec: |
|||
<lang PureBasic>rec: |
|||
PrintN(str(n)) |
PrintN(str(n)) |
||
n+1 |
n+1 |
||
Gosub rec |
Gosub rec |
||
Return</ |
Return</syntaxhighlight> |
||
Stack overflow after 258931 recursions on x86 Vista. |
Stack overflow after 258931 recursions on x86 Vista. |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">import sys |
||
print(sys.getrecursionlimit())</ |
print(sys.getrecursionlimit())</syntaxhighlight> |
||
To set it: |
To set it: |
||
< |
<syntaxhighlight lang="python">import sys |
||
sys.setrecursionlimit(12345)</ |
sys.setrecursionlimit(12345)</syntaxhighlight> |
||
Or, we can test it: |
Or, we can test it: |
||
< |
<syntaxhighlight lang="python">def recurse(counter): |
||
print(counter) |
print(counter) |
||
counter += 1 |
counter += 1 |
||
recurse(counter)</ |
recurse(counter)</syntaxhighlight> |
||
Giving: |
Giving: |
||
< |
<syntaxhighlight lang="python">File "<stdin>", line 2, in recurse |
||
RecursionError: maximum recursion depth exceeded while calling a Python object |
RecursionError: maximum recursion depth exceeded while calling a Python object |
||
996</ |
996</syntaxhighlight> |
||
Which we could change if we wanted to. |
Which we could change if we wanted to. |
||
Line 2,589: | Line 2,589: | ||
We can catch the RecursionError and keep going a bit further: |
We can catch the RecursionError and keep going a bit further: |
||
< |
<syntaxhighlight lang="python">def recurseDeeper(counter): |
||
try: |
try: |
||
print(counter) |
print(counter) |
||
Line 2,595: | Line 2,595: | ||
except RecursionError: |
except RecursionError: |
||
print("RecursionError at depth", counter) |
print("RecursionError at depth", counter) |
||
recurseDeeper(counter + 1)</ |
recurseDeeper(counter + 1)</syntaxhighlight> |
||
Giving: |
Giving: |
||
< |
<syntaxhighlight lang="python">1045 |
||
Fatal Python error: Cannot recover from stack overflow.</ |
Fatal Python error: Cannot recover from stack overflow.</syntaxhighlight> |
||
Line 2,606: | Line 2,606: | ||
When the direct approach |
When the direct approach |
||
< |
<syntaxhighlight lang="quackery">0 [ 1+ dup echo cr recurse ]</syntaxhighlight> |
||
was still churning out digits after 13,000,000 (Quackery does not optimise tail end recursion) I decided on an indirect approach, by asking the equivalent question, "What is the largest nest that Quackery can create?" as each item on the Quackery return stack occupies two items in a nest (i.e. dynamic array). |
was still churning out digits after 13,000,000 (Quackery does not optimise tail end recursion) I decided on an indirect approach, by asking the equivalent question, "What is the largest nest that Quackery can create?" as each item on the Quackery return stack occupies two items in a nest (i.e. dynamic array). |
||
< |
<syntaxhighlight lang="quackery">' [ 1 ] [ dup size echo cr dup join again ]</syntaxhighlight> |
||
On the first trial the process died with a segmentation error after reaching 2^30 items, and on the second trial the computer became very unresponsive at the same point, but made it to 2^31 items before I force-quit it. |
On the first trial the process died with a segmentation error after reaching 2^30 items, and on the second trial the computer became very unresponsive at the same point, but made it to 2^31 items before I force-quit it. |
||
Line 2,619: | Line 2,619: | ||
=={{header|R}}== |
=={{header|R}}== |
||
R's recursion is counted by the number of expressions to be evaluated, rather than the number of function calls. |
R's recursion is counted by the number of expressions to be evaluated, rather than the number of function calls. |
||
< |
<syntaxhighlight lang="r">#Get the limit |
||
options("expressions") |
options("expressions") |
||
Line 2,632: | Line 2,632: | ||
} |
} |
||
recurse(0)</ |
recurse(0)</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(define (recursion-limit) |
(define (recursion-limit) |
||
(with-handlers ((exn? (lambda (x) 0))) |
(with-handlers ((exn? (lambda (x) 0))) |
||
(add1 (recursion-limit))))</ |
(add1 (recursion-limit))))</syntaxhighlight> |
||
This should theoretically return the recursion limit, as the function can't be tail-optimized and there's an exception handler to return a number when an error is encountered. For this to work one has to give the Racket VM the maximum possible memory limit and wait. |
This should theoretically return the recursion limit, as the function can't be tail-optimized and there's an exception handler to return a number when an error is encountered. For this to work one has to give the Racket VM the maximum possible memory limit and wait. |
||
Line 2,646: | Line 2,646: | ||
Maximum recursion depth is memory dependent. Values in excess of 1 million are easily achieved. |
Maximum recursion depth is memory dependent. Values in excess of 1 million are easily achieved. |
||
{{works with|Rakudo|2015.12}} |
{{works with|Rakudo|2015.12}} |
||
<lang |
<syntaxhighlight lang="raku" line>my $x = 0; |
||
recurse; |
recurse; |
||
Line 2,653: | Line 2,653: | ||
say $x if $x %% 1_000_000; |
say $x if $x %% 1_000_000; |
||
recurse; |
recurse; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,675: | Line 2,675: | ||
When run, this will display the address stack depth until it reaches the max depth. Once the address stack is full, Retro will crash. |
When run, this will display the address stack depth until it reaches the max depth. Once the address stack is full, Retro will crash. |
||
< |
<syntaxhighlight lang="retro">: try -6 5 out wait 5 in putn cr try ;</syntaxhighlight> |
||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Line 2,684: | Line 2,684: | ||
This limit was maybe changed later to allow the user to specify the limit. My memory is really fuzzy |
This limit was maybe changed later to allow the user to specify the limit. My memory is really fuzzy |
||
<br>about these details, it was over thirty years ago. |
<br>about these details, it was over thirty years ago. |
||
< |
<syntaxhighlight lang="rexx">/*REXX program finds the recursion limit: a subroutine that repeatably calls itself. */ |
||
parse version x; say x; say /*display which REXX is being used. */ |
parse version x; say x; say /*display which REXX is being used. */ |
||
#=0 /*initialize the numbers of invokes to 0*/ |
#=0 /*initialize the numbers of invokes to 0*/ |
||
Line 2,694: | Line 2,694: | ||
#=#+1 /*bump number of times SELF is invoked. */ |
#=#+1 /*bump number of times SELF is invoked. */ |
||
say # /*display the number of invocations. */ |
say # /*display the number of invocations. */ |
||
call self /*invoke ourselves recursively. */</ |
call self /*invoke ourselves recursively. */</syntaxhighlight> |
||
{{out|output|text= when using Regina 3.6 under Windows/XP Pro:}} |
{{out|output|text= when using Regina 3.6 under Windows/XP Pro:}} |
||
<pre> |
<pre> |
||
Line 2,768: | Line 2,768: | ||
===recursive subroutine=== |
===recursive subroutine=== |
||
All REXXes were executed under Windows/XP Pro. |
All REXXes were executed under Windows/XP Pro. |
||
< |
<syntaxhighlight lang="rexx">/*REXX program finds the recursion limit: a subroutine that repeatably calls itself. */ |
||
parse version x; say x; say /*display which REXX is being used. */ |
parse version x; say x; say /*display which REXX is being used. */ |
||
#=0 /*initialize the numbers of invokes to 0*/ |
#=0 /*initialize the numbers of invokes to 0*/ |
||
Line 2,777: | Line 2,777: | ||
self: #=#+1 /*bump number of times SELF is invoked. */ |
self: #=#+1 /*bump number of times SELF is invoked. */ |
||
say # /*display the number of invocations. */ |
say # /*display the number of invocations. */ |
||
call self /*invoke ourselves recursively. */</ |
call self /*invoke ourselves recursively. */</syntaxhighlight> |
||
{{out|output|text= (paraphrased and edited)}} |
{{out|output|text= (paraphrased and edited)}} |
||
<pre> |
<pre> |
||
Line 2,801: | Line 2,801: | ||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
recurse(0) |
recurse(0) |
||
Line 2,807: | Line 2,807: | ||
see ""+ x + nl |
see ""+ x + nl |
||
recurse(x+1) |
recurse(x+1) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">def recurse x |
||
puts x |
puts x |
||
recurse(x+1) |
recurse(x+1) |
||
end |
end |
||
recurse(0)</ |
recurse(0)</syntaxhighlight> |
||
{{out}} Produces a SystemStackError: |
{{out}} Produces a SystemStackError: |
||
<pre> |
<pre> |
||
Line 2,829: | Line 2,829: | ||
when tracking Stack overflow exceptions ; returns 8732 on my computer : |
when tracking Stack overflow exceptions ; returns 8732 on my computer : |
||
< |
<syntaxhighlight lang="ruby">def recurse n |
||
recurse(n+1) |
recurse(n+1) |
||
rescue SystemStackError |
rescue SystemStackError |
||
Line 2,835: | Line 2,835: | ||
end |
end |
||
puts recurse(0)</ |
puts recurse(0)</syntaxhighlight> |
||
=={{header|Run BASIC}}== |
=={{header|Run BASIC}}== |
||
< |
<syntaxhighlight lang="runbasic">a = recurTest(1) |
||
function recurTest(n) |
function recurTest(n) |
||
Line 2,845: | Line 2,845: | ||
n = recurTest(n+1) |
n = recurTest(n+1) |
||
[ext] |
[ext] |
||
end function</ |
end function</syntaxhighlight> |
||
<pre>327000</pre> |
<pre>327000</pre> |
||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
< |
<syntaxhighlight lang="rust">fn recurse(n: i32) { |
||
println!("depth: {}", n); |
println!("depth: {}", n); |
||
recurse(n + 1) |
recurse(n + 1) |
||
Line 2,856: | Line 2,856: | ||
fn main() { |
fn main() { |
||
recurse(0); |
recurse(0); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,870: | Line 2,870: | ||
=={{header|Sather}}== |
=={{header|Sather}}== |
||
< |
<syntaxhighlight lang="sather">class MAIN is |
||
attr r:INT; |
attr r:INT; |
||
recurse is |
recurse is |
||
Line 2,881: | Line 2,881: | ||
recurse; |
recurse; |
||
end; |
end; |
||
end;</ |
end;</syntaxhighlight> |
||
Segmentation fault is reached when r is 130560. |
Segmentation fault is reached when r is 130560. |
||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
< |
<syntaxhighlight lang="scala">def recurseTest(i:Int):Unit={ |
||
try{ |
try{ |
||
recurseTest(i+1) |
recurseTest(i+1) |
||
Line 2,893: | Line 2,893: | ||
} |
} |
||
} |
} |
||
recurseTest(0)</ |
recurseTest(0)</syntaxhighlight> |
||
{{out}} depending on the current stack size: |
{{out}} depending on the current stack size: |
||
<pre>Recursion depth on this system is 4869.</pre> |
<pre>Recursion depth on this system is 4869.</pre> |
||
If your function is tail-recursive the compiler transforms it into a loop. |
If your function is tail-recursive the compiler transforms it into a loop. |
||
< |
<syntaxhighlight lang="scala">def recurseTailRec(i:Int):Unit={ |
||
if(i%100000==0) println("Recursion depth is " + i + ".") |
if(i%100000==0) println("Recursion depth is " + i + ".") |
||
recurseTailRec(i+1) |
recurseTailRec(i+1) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
< |
<syntaxhighlight lang="scheme">(define (recurse number) |
||
(begin (display number) (newline) (recurse (+ number 1)))) |
(begin (display number) (newline) (recurse (+ number 1)))) |
||
(recurse 1)</ |
(recurse 1)</syntaxhighlight> |
||
Implementations of Scheme are required to support an unbounded number of tail calls. Furthermore, implementations are encouraged, but not required, to support exact integers of practically unlimited size. |
Implementations of Scheme are required to support an unbounded number of tail calls. Furthermore, implementations are encouraged, but not required, to support exact integers of practically unlimited size. |
||
=={{header|SenseTalk}}== |
=={{header|SenseTalk}}== |
||
< |
<syntaxhighlight lang="sensetalk">put recurse(1) |
||
function recurse n |
function recurse n |
||
put n |
put n |
||
get the recurse of (n+1) |
get the recurse of (n+1) |
||
end recurse</ |
end recurse</syntaxhighlight> |
||
Recursion limit error is reached at 40. |
Recursion limit error is reached at 40. |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
Maximum recursion depth is memory dependent. |
Maximum recursion depth is memory dependent. |
||
< |
<syntaxhighlight lang="ruby">func recurse(n) { |
||
say n; |
say n; |
||
recurse(n+1); |
recurse(n+1); |
||
} |
} |
||
recurse(0);</ |
recurse(0);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,942: | Line 2,942: | ||
In the Squeak dialect of Smalltalk: |
In the Squeak dialect of Smalltalk: |
||
< |
<syntaxhighlight lang="smalltalk"> |
||
Object subclass: #RecursionTest |
Object subclass: #RecursionTest |
||
instanceVariableNames: '' |
instanceVariableNames: '' |
||
Line 2,948: | Line 2,948: | ||
poolDictionaries: '' |
poolDictionaries: '' |
||
category: 'RosettaCode' |
category: 'RosettaCode' |
||
</syntaxhighlight> |
|||
</lang> |
|||
Add the following method: |
Add the following method: |
||
< |
<syntaxhighlight lang="smalltalk"> |
||
counter: aNumber |
counter: aNumber |
||
^self counter: aNumber + 1 |
^self counter: aNumber + 1 |
||
</syntaxhighlight> |
|||
</lang> |
|||
Call from the Workspace: |
Call from the Workspace: |
||
< |
<syntaxhighlight lang="smalltalk"> |
||
r := RecursionTest new. |
r := RecursionTest new. |
||
r counter: 1. |
r counter: 1. |
||
</syntaxhighlight> |
|||
</lang> |
|||
After some time the following error pops up: |
After some time the following error pops up: |
||
Line 2,977: | Line 2,977: | ||
Other dialects raise an exception: |
Other dialects raise an exception: |
||
< |
<syntaxhighlight lang="smalltalk"> |
||
counter := 0. |
counter := 0. |
||
down := [ counter := counter + 1. down value ]. |
down := [ counter := counter + 1. down value ]. |
||
down on: RecursionError do:[ |
down on: RecursionError do:[ |
||
'depth is ' print. counter printNL |
'depth is ' print. counter printNL |
||
].</ |
].</syntaxhighlight> |
||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
||
< |
<syntaxhighlight lang="sml">fun recLimit () = |
||
1 + recLimit () |
1 + recLimit () |
||
handle _ => 0 |
handle _ => 0 |
||
val () = print (Int.toString (recLimit ()) ^ "\n")</ |
val () = print (Int.toString (recLimit ()) ^ "\n")</syntaxhighlight> |
||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
< |
<syntaxhighlight lang="swift">var n = 1 |
||
func recurse() { |
func recurse() { |
||
Line 3,000: | Line 3,000: | ||
} |
} |
||
recurse()</ |
recurse()</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">proc recur i { |
||
puts "This is depth [incr i]" |
puts "This is depth [incr i]" |
||
catch {recur $i}; # Trap error from going too deep |
catch {recur $i}; # Trap error from going too deep |
||
} |
} |
||
recur 0</ |
recur 0</syntaxhighlight> |
||
The tail of the execution trace looks like this: |
The tail of the execution trace looks like this: |
||
<pre> |
<pre> |
||
Line 3,017: | Line 3,017: | ||
</pre> |
</pre> |
||
Note that the maximum recursion depth is a tunable parameter, as is shown in this program: |
Note that the maximum recursion depth is a tunable parameter, as is shown in this program: |
||
< |
<syntaxhighlight lang="tcl"># Increase the maximum depth |
||
interp recursionlimit {} 1000000 |
interp recursionlimit {} 1000000 |
||
proc recur i { |
proc recur i { |
||
Line 3,025: | Line 3,025: | ||
} |
} |
||
} |
} |
||
recur 0</ |
recur 0</syntaxhighlight> |
||
For Tcl 8.5 on this platform, this prints: |
For Tcl 8.5 on this platform, this prints: |
||
<pre> |
<pre> |
||
Line 3,036: | Line 3,036: | ||
=={{header|TSE SAL}}== |
=={{header|TSE SAL}}== |
||
<syntaxhighlight lang="tse sal"> |
|||
<lang TSE SAL> |
|||
// library: program: run: recursion: limit <description>will stop at 3616</description> <version>1.0.0.0.3</version> <version control></version control> (filenamemacro=runprrli.s) [kn, ri, su, 25-12-2011 23:12:02] |
// library: program: run: recursion: limit <description>will stop at 3616</description> <version>1.0.0.0.3</version> <version control></version control> (filenamemacro=runprrli.s) [kn, ri, su, 25-12-2011 23:12:02] |
||
PROC PROCProgramRunRecursionLimit( INTEGER I ) |
PROC PROCProgramRunRecursionLimit( INTEGER I ) |
||
Line 3,046: | Line 3,046: | ||
PROCProgramRunRecursionLimit( 1 ) |
PROCProgramRunRecursionLimit( 1 ) |
||
END |
END |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|TXR}}== |
=={{header|TXR}}== |
||
< |
<syntaxhighlight lang="txrlisp">(set-sig-handler sig-segv |
||
(lambda (signal async-p) (throw 'out))) |
(lambda (signal async-p) (throw 'out))) |
||
Line 3,060: | Line 3,060: | ||
(catch (recurse) |
(catch (recurse) |
||
(out () (put-line `caught segfault!\nreached depth: @{*count*}`)))</ |
(out () (put-line `caught segfault!\nreached depth: @{*count*}`)))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,071: | Line 3,071: | ||
{{works with|Bourne Again SHell}} |
{{works with|Bourne Again SHell}} |
||
< |
<syntaxhighlight lang="bash">recurse() |
||
{ |
{ |
||
# since the example runs slowly, the following |
# since the example runs slowly, the following |
||
Line 3,085: | Line 3,085: | ||
} |
} |
||
recurse 0</ |
recurse 0</syntaxhighlight> |
||
The Bash reference manual says <cite>No limit is placed on the number of recursive calls</cite>, nonetheless a segmentation fault occurs at 13777 (Bash v3.2.19 on 32bit GNU/Linux) |
The Bash reference manual says <cite>No limit is placed on the number of recursive calls</cite>, nonetheless a segmentation fault occurs at 13777 (Bash v3.2.19 on 32bit GNU/Linux) |
||
=={{header|Ursa}}== |
=={{header|Ursa}}== |
||
< |
<syntaxhighlight lang="ursa">def recurse (int counter) |
||
try |
try |
||
recurse (+ counter 1) |
recurse (+ counter 1) |
||
Line 3,098: | Line 3,098: | ||
end |
end |
||
recurse 1</ |
recurse 1</syntaxhighlight> |
||
=={{header|Vala}}== |
=={{header|Vala}}== |
||
< |
<syntaxhighlight lang="vala">void recur(uint64 v ) { |
||
print (@"$v\n"); |
print (@"$v\n"); |
||
recur( v + 1); |
recur( v + 1); |
||
Line 3,108: | Line 3,108: | ||
void main() { |
void main() { |
||
recur(0); |
recur(0); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
trimmed output |
trimmed output |
||
Line 3,122: | Line 3,122: | ||
=={{header|VBA}}== |
=={{header|VBA}}== |
||
<syntaxhighlight lang="vb"> |
|||
<lang vb> |
|||
Option Explicit |
Option Explicit |
||
Line 3,136: | Line 3,136: | ||
Limite_Recursivite = Cpt 'return |
Limite_Recursivite = Cpt 'return |
||
End Function |
End Function |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>The limit is : 6442</pre> |
<pre>The limit is : 6442</pre> |
||
Line 3,143: | Line 3,143: | ||
Haven't figured out how to see the depth. And this depth is that of calling the O/S rather than calling within. |
Haven't figured out how to see the depth. And this depth is that of calling the O/S rather than calling within. |
||
< |
<syntaxhighlight lang="vb">'mung.vbs |
||
option explicit |
option explicit |
||
Line 3,155: | Line 3,155: | ||
wscript.echo "[Depth",c & "] Mung until no good." |
wscript.echo "[Depth",c & "] Mung until no good." |
||
CreateObject("WScript.Shell").Run "cscript Mung.vbs " & c, 1, true |
CreateObject("WScript.Shell").Run "cscript Mung.vbs " & c, 1, true |
||
wscript.echo "[Depth",c & "] no good."</ |
wscript.echo "[Depth",c & "] no good."</syntaxhighlight> |
||
Okay, the internal limits version. |
Okay, the internal limits version. |
||
< |
<syntaxhighlight lang="vb">'mung.vbs |
||
option explicit |
option explicit |
||
Line 3,172: | Line 3,172: | ||
end sub |
end sub |
||
mung 0</ |
mung 0</syntaxhighlight> |
||
{{out}} (abbrev.): |
{{out}} (abbrev.): |
||
Line 3,186: | Line 3,186: | ||
=={{header|Vlang}}== |
=={{header|Vlang}}== |
||
It'll be some number, depending on machine and environment. |
It'll be some number, depending on machine and environment. |
||
< |
<syntaxhighlight lang="go">// Find limit of recursion, in V |
||
module main |
module main |
||
Line 3,197: | Line 3,197: | ||
println(n) |
println(n) |
||
recurse(n+1) |
recurse(n+1) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>prompt$ v run find-limit-of-recursion.v |
<pre>prompt$ v run find-limit-of-recursion.v |
||
Line 3,210: | Line 3,210: | ||
{{works with|nasm}} |
{{works with|nasm}} |
||
< |
<syntaxhighlight lang="asm"> global main |
||
section .text |
section .text |
||
Line 3,222: | Line 3,222: | ||
add eax, 1 |
add eax, 1 |
||
call recurse |
call recurse |
||
ret</ |
ret</syntaxhighlight> |
||
I've used gdb and the command <tt>print $eax</tt> to know when the segmentation fault occurred. The result was 2094783. |
I've used gdb and the command <tt>print $eax</tt> to know when the segmentation fault occurred. The result was 2094783. |
||
Line 3,232: | Line 3,232: | ||
In Wren a fiber's stack starts small and is increased as required. It appears that the runtime makes no attempt to check for any limitation internally leaving the script to eventually segfault. |
In Wren a fiber's stack starts small and is increased as required. It appears that the runtime makes no attempt to check for any limitation internally leaving the script to eventually segfault. |
||
< |
<syntaxhighlight lang="ecmascript">var f |
||
f = Fn.new { |n| |
f = Fn.new { |n| |
||
if (n%500 == 0) System.print(n) // print progress after every 500 calls |
if (n%500 == 0) System.print(n) // print progress after every 500 calls |
||
Line 3,238: | Line 3,238: | ||
f.call(n + 1) |
f.call(n + 1) |
||
} |
} |
||
f.call(1)</ |
f.call(1)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,255: | Line 3,255: | ||
(For a more realistic example see this task's entry for 8080 Assembly.) |
(For a more realistic example see this task's entry for 8080 Assembly.) |
||
< |
<syntaxhighlight lang="z80">org &0000 |
||
LD SP,&FFFF ;3 bytes |
LD SP,&FFFF ;3 bytes |
||
loop: |
loop: |
||
Line 3,267: | Line 3,267: | ||
jr * ;2 bytes |
jr * ;2 bytes |
||
;address &0024 begins here |
;address &0024 begins here |
||
word 0 ;placeholder for stack pointer</ |
word 0 ;placeholder for stack pointer</syntaxhighlight> |
||
This is the minimum amount of code I can come up with that can check for the limit. (Note that this code has no way to display the results of the test to the user, so on real hardware the limit of recursion is much less, but for an emulator this will suffice.) The concept here is relatively simple. Do the following in a loop: |
This is the minimum amount of code I can come up with that can check for the limit. (Note that this code has no way to display the results of the test to the user, so on real hardware the limit of recursion is much less, but for an emulator this will suffice.) The concept here is relatively simple. Do the following in a loop: |
||
Line 3,278: | Line 3,278: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
<lang |
<syntaxhighlight lang="zkl">fcn{self.fcn()}()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |