Anonymous user
Man or boy test: Difference between revisions
→F#: Add CPS version of straightforward approach.
imported>GLChapman (→F#: Add CPS version of straightforward approach.) |
|||
(33 intermediate revisions by 18 users not shown) | |||
Line 227:
* [[Jensen's Device]]
<br>
=={{header|Ada}}==
Line 234 ⟶ 233:
{{works with|Ada|Ada|2005, 2012}}
<
procedure Man_Or_Boy is
Line 269 ⟶ 268:
Zero'Access -- Returns 0
) ) );
end Man_Or_Boy;</
Ada 2012 supports expression functions and conditional expressions which are used in the implementation below:
Line 275 ⟶ 274:
{{works with|Ada|Ada|2012}}
<
procedure Man_Or_Boy is
Line 304 ⟶ 303:
X4 => One'Access,
X5 => Zero'Access)));
end Man_Or_Boy;</
This version resembles more Knuth's original version in that the result of B is thrown away.
<
use Ada.Text_IO;
Line 348 ⟶ 347:
X5 => Zero'Access)));
end Man_Or_Boy;</
Sample output:
Line 356 ⟶ 355:
=={{header|Aime}}==
<
F(list l)
{
Line 407 ⟶ 406:
0;
}</
Output:
<pre>
Line 413 ⟶ 412:
</pre>
=={{header|ALGOL 60}}
Knuth's example:
'''begin'''
'''real''' '''procedure''' A (k, x1, x2, x3, x4, x5);
Line 452:
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of FORMATted transput}}
[[wp:Charles_H._Lindsey|Charles H. Lindsey]] implemented this [http://archive.computerhistory.org/resources/text/algol/algol_bulletin/A52/P43.HTM man boy test] in [[ALGOL 68]], and - as call by name is not necessary - the same algorithm can be implemented in many languages including [[:Category:Pascal|Pascal]] and [[:Category:PL/I|PL/I]] <!-- <ref>{{cite web|title=Block Structure and Environments | author=[[Charles H. Lindsey]] | url=http://archive.computerhistory.org/resources/text/algol/algol_bulletin/A52/P43.HTM | accessyear=2007 | accessmonthday=May 2| year=1988 | month=Dec}}</ref>. --> <!-- <ref>{{cite web|title="Man or boy" test|url=http://groups.google.com/group/comp.lang.haskell/browse_thread/thread/eef78beaaac73b26/7a6672ceea07b34e}}</ref>, -->.
<
INT k := in k;
PROC b = INT: a(k-:=1, b, xl, x2, x3, x4);
Line 460:
test:(
printf(($gl$,a(10, INT:1, INT:-1, INT:-1, INT:1, INT:0)))
)</
Output:
<pre>
-67
</pre>
=={{header|ALGOL W}}==
{{Trans|ALGOL 60}}
Algol 60 has two parameter passing modes: by value and by name, Algol W has these plus a number of others. In Algol W, an expression is automatically converted to a procedure (by the compiler) if it is used as a parameter to a procedure that is expecting a procedure - this is used in the following. The sample below is thus similar to the Algol 68 sample above, but without the need for routine texts for the literals 1, -1, etc. as these are generated automatically.
<p>
Note that unlike Algol 60, in Algol W the result of a procedure is the final value calculated by the procedure and so the result cannot be assigned in a sub-procedure. This means the following sample is "strictly incorrect" (see the notes on the Algol 60 sample) but yields the correct result.
<syntaxhighlight lang="algolw">begin
real procedure A (integer value k; real procedure x1, x2, x3, x4, x5);
begin
real procedure B;
begin k:= k - 1;
A (k, B, x1, x2, x3, x4)
end;
if k <= 0 then x4 + x5 else B
end;
write (r_format := "A", r_w := 8, r_d := 2, A (10, 1, -1, -1, 1, 0))
end.</syntaxhighlight>
{{out}}
<pre>
-67.00
</pre>
Line 471 ⟶ 492:
AppleScript's stack limit is around 500 frames, which is too low to run this example. It runs in the compatible [http://en.wikipedia.org/wiki/Smile_%28software%29 Smile] environment, however.
<
script b
set k to k - 1
Line 491 ⟶ 512:
a(10, int(1), int(-1), int(-1), int(1), int(0))
</syntaxhighlight>
Output:
<pre>
Line 497 ⟶ 518:
</pre>
=={{header|
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<
FOR k% = 0 TO 20
Line 523 ⟶ 545:
DEF FN0(d%) = 0
DEF FN1(d%) = 1
DEF FN_1(d%) = -1</
Output:
<pre>
Line 553 ⟶ 575:
Even if [[closures]] are not available in a language, their effect can be simulated. This is what happens in the following C implementation:
<
#include <stdio.h>
#include <stdlib.h>
Line 595 ⟶ 617:
MAKE_ARG(f1), MAKE_ARG(f0))));
return 0;
}</
Two gcc extensions to the C language, nested functions and block sub-expressions, can be combined to create this elegant version:
Version: gcc version 4.1.2 20070925 (Red Hat 4.1.2-27)
<
#define INT(body) ({ int lambda(){ body; }; lambda; })
main(){
Line 610 ⟶ 632:
}
printf(" %d\n",a(10, INT(return 1), INT(return -1), INT(return -1), INT(return 1), INT(return 0)));
}</
C without C99 or gcc extensions:
<
#include <stdlib.h>
Line 660 ⟶ 682:
printf("%d\n", A(Frame(&a, &k, &f1, &fn1, &fn1, &f1, &f0)));
return 0;
}</
Output:
-67
=={{header|C sharp|C#}}==
C# 2.0 supports anonymous methods which are used in the implementation below:
{{works with|C sharp|C#|2+}}
<syntaxhighlight lang="csharp">using System;
delegate T Func<T>();
class ManOrBoy
{
static void Main()
{
Console.WriteLine(A(10, C(1), C(-1), C(-1), C(1), C(0)));
}
static Func<int> C(int i)
{
return delegate { return i; };
}
static int A(int k, Func<int> x1, Func<int> x2, Func<int> x3, Func<int> x4, Func<int> x5)
{
Func<int> b = null;
b = delegate { k--; return A(k, b, x1, x2, x3, x4); };
return k <= 0 ? x4() + x5() : b();
}
}
</syntaxhighlight>
C# 3.0 supports lambda expressions which are used in the implementation below:
{{works with|C sharp|C#|3+}}
<syntaxhighlight lang="csharp">using System;
class ManOrBoy
{
static void Main()
{
Console.WriteLine(A(10, () => 1, () => -1, () => -1, () => 1, () => 0));
}
static int A(int k, Func<int> x1, Func<int> x2, Func<int> x3, Func<int> x4, Func<int> x5)
{
Func<int> b = null;
b = () => { k--; return A(k, b, x1, x2, x3, x4); };
return k <= 0 ? x4() + x5() : b();
}
}</syntaxhighlight>
=={{header|C++}}==
Line 670 ⟶ 743:
Uses "shared_ptr" smart pointers from Boost / TR1 to automatically deallocate objects. Since we have an object which needs to pass a pointer to itself to another function, we need to use "enable_shared_from_this".
<
#include <tr1/memory>
using std::tr1::shared_ptr;
Line 722 ⟶ 795:
shared_ptr<Arg>(new Const(0))) << std::endl;
return 0;
}</
{{works with|C++11}} uses anonymous functions. Tested with g++ version 4.5 and Visual C++ version 16 (Windows SDK 7.1):
<
#include <iostream>
Line 749 ⟶ 822:
std::cout << A(10, L(1), L(-1), L(-1), L(1), L(0)) << std::endl;
return 0;
}</
{{works with|TR1}} uses TR1 without C++11.
<
#include <iostream>
Line 783 ⟶ 856:
std::cout << A(10, L(1), L(-1), L(-1), L(1), L(0)) << std::endl;
return 0;
}</
=={{header|Clipper}}==
<
Local k
For k := 0 to 20
Line 862 ⟶ 884:
xVal := x
Endif
Return xVal</
Line 896 ⟶ 918:
=={{header|Clojure}}==
<
(defn man-or-boy
Line 920 ⟶ 942:
(man-or-boy 10)
</syntaxhighlight>
=={{header|Common Lisp}}==
<
(a x (lambda () 1)
(lambda () -1)
Line 939 ⟶ 961:
(b))))
(man-or-boy 10)</
=={{header|Crystal}}==
<
b = uninitialized -> typeof(k)
b = ->() { k -= 1; a(k, b, x1, x2, x3, x4) }
Line 948 ⟶ 970:
end
puts a(10, -> {1}, -> {-1}, -> {-1}, -> {1}, -> {0})</
{{out}}
<pre>
Line 956 ⟶ 978:
=={{header|D}}==
===Straightforward Version===
<
int a(int k, const lazy int x1, const lazy int x2, const lazy int x3,
Line 969 ⟶ 991:
void main() {
printf("%d\n", a(10, 1, -1, -1, 1, 0));
}</
The DMD compiler is a man. Increasing the maximum stack space to about 1.2 GB the DMD 2.059 compiler computes the result -9479595 for k = 25 in about 6.5 seconds on a 32 bit system (-inline -O -release -L/STACK:1300000000).
Line 975 ⟶ 997:
[http://www.digitalmars.com/d/1.0/function.html Lazy Variadic Functions] version, as quoted:<br>
:If the variadic parameter is an array of delegates with no parameters:<br><tt> void foo(int delegate()[] dgs ...);</tt><br>Then each of the arguments whose type does not match that of the delegate is converted to a delegate.<br><tt> int delegate() dg;</tt><br><tt> foo(1, 3+x, dg, cast(int delegate())null);</tt><br>is the same as:<br><tt> foo( { return 1; }, { return 3+x; }, dg, null );</tt><br>
<
int b() nothrow @safe {
k--;
Line 988 ⟶ 1,010:
A(10, 1, -1, -1, 1, 0).writeln;
}</
===Template Version===
<
int b() nothrow @safe @nogc {
static if (is(T == int))
Line 1,018 ⟶ 1,040:
A(10, 1, -1, -1, 1, 0).writeln;
}</
===Anonymous Class Version===
Similar to Java example:
<
interface B {
Line 1,061 ⟶ 1,083:
void main() {
writeln(A(10, 1, -1, -1, 1, 0));
}</
===Faster Version===
This version cheats, using a different much faster algorithm.
<
// Adapted from C code by Goran Weinholt, adapted from Knuth code.
Line 1,121 ⟶ 1,143:
writefln("...\n500 %-(%s\\\n %)",
A(500, 1, -1, -1, 1, 0).text.chunks(60));
}</
{{out}}
<pre>0 1
Line 1,172 ⟶ 1,194:
The latest editions of Delphi support anonymous methods, providing a way to implement call by name semantics.
<
TFunc<T> = reference to function: T;
Line 1,200 ⟶ 1,222:
begin
Writeln(A(10, C(1), C(-1), C(-1), C(1), C(0))); // -67 output
end.</
=={{header|Dyalect}}==
<
() => i
}
func
var b
b = () => {
k -= 1
}
if k <= 0 {
Line 1,238 ⟶ 1,242:
}
}
for i in 1..20 {
let res = _A(i, _C(1), _C(-1), _C(-1), _C(1), _C(0))
print("\(i)\t= \(res)")
}</syntaxhighlight>
{{out}}
<pre>
2 = -2
3 = 0
4 = 1
5 = 0
6 = 1
7 = -1
8 = -10
9 = -30
10 = -67
11 = -138
12 = -291
13 = -642
14 = -1446
15 = -3250
16 = -7244
17 = -16065
18 = -35601
19 = -78985
20 = -175416</pre>
=={{header|Dylan}}==
<
(k :: <integer>, x1 :: <function>, x2 :: <function>, x3 :: <function>,
x4 :: <function>, x5 :: <function>)
Line 1,272 ⟶ 1,298:
end method man-or-boy;
format-out("%d\n", man-or-boy(10))</
=={{header|Déjà Vu}}==
{{trans|Python}}
<syntaxhighlight lang="dejavu">a k x1 x2 x3 x4 x5:
local b:
set :k -- k
a k @b @x1 @x2 @x3 @x4
if <= k 0:
+ x4 x5
else:
b
local x i:
labda:
i
!. a 10 x 1 x -1 x -1 x 1 x 0</syntaxhighlight>
=={{header|E}}==
Line 1,278 ⟶ 1,322:
Provided that it is marked in the caller and callee, E can perfectly emulate the requested [[wp:Call-by-name#Call_by_name|call-by-name]] behavior by passing slots instead of values:
<
def bS; def &b := bS
bind bS {
Line 1,292 ⟶ 1,336:
def n := -1
def z := 0
println(a(10, &p, &n, &n, &p, &z))</
Here each of the "<code>x</code>" parameters is effectively call-by-name. <var><code>b</code></var> is bound to a custom slot definition.
=={{header|EchoLisp}}==
<
;; copied from Scheme
(define (A k x1 x2 x3 x4 x5)
Line 1,314 ⟶ 1,358:
❗ InternalError : too much recursion - JS internal error (please, report it)-
→ stack overflow using FireFox
</syntaxhighlight>
=={{header|Ela}}==
Line 1,321 ⟶ 1,364:
Stack overflow is not a problem in Ela (but "out of memory" is):
<
liftM2 f m1 m2 = do
Line 1,335 ⟶ 1,378:
_ = a 10 (!!1) (!! -1) (!! -1) (!!1) (!!0) >>= (putStr << show) ::: IO
where (!!) f = & return f ::: IO</
=={{header|Elena}}==
ELENA
<
A(k,x1,x2,x3,x4,x5)
{
var m := new
var b := { m -= 1; ^ A(m,this self,x1,x2,x3,x4) };
if (m <= 0)
Line 1,358 ⟶ 1,402:
public program()
{
for(int n := 0
{
console.printLine(A(n,
}
}</
{{out}}
<pre>
Line 1,380 ⟶ 1,424:
-642
-1446
</pre>
=={{header|Elixir}}==
The solution is gracefully stolen from Erlang one (see below).
<pre>
kounter = fn k, kounter ->
receive do
{:decr, pid} ->
send(pid, k - 1)
kounter.(k - 1, kounter)
_ -> :ok
end
end
a = fn k, x1, x2, x3, x4, x5, a ->
kounter_process = spawn(fn -> kounter.(k, kounter) end)
b =
fn b ->
send(kounter_process, {:decr, self()})
receive do
pred -> a.(pred, fn -> b.(b) end, x1, x2, x3, x4, a)
end
end
if k <= 0,
do: send(kounter_process, x4.() + x5.()),
else: send(kounter_process, b.(b))
end
man_or_boy = fn n ->
a.(n, fn -> 1 end, fn -> -1 end, fn -> -1 end, fn -> 1 end, fn -> 0 end, a)
end
▶ man_or_boy.(10) #⇒ -67
▶ man_or_boy.(14) #⇒ -1446
▶ man_or_boy.(20) #⇒ [error] Too many processes
</pre>
=={{header|EMal}}==
<syntaxhighlight lang="emal">
fun A = int by int k, fun x1, fun x2, fun x3, fun x4, fun x5
fun B = int by block do return A(--k, B, x1, x2, x3, x4) end
return when(k <= 0, x4() + x5(), B())
end
fun C = fun by int i
return int by block do return i end
end
for int i = 0; i <= 11; i++
writeLine("A(" + i + ") = " + A(i, C(1), C(-1), C(-1), C(1), C(0) ))
end
</syntaxhighlight>
{{out}}
<pre>
A(0) = 1
A(1) = 0
A(2) = -2
A(3) = 0
A(4) = 1
A(5) = 0
A(6) = 1
A(7) = -1
A(8) = -10
A(9) = -30
A(10) = -67
A(11) = -138
</pre>
Line 1,413 ⟶ 1,523:
Straightforward version:
<
[<EntryPoint>]
let main (args : string[]) =
Line 1,434 ⟶ 1,544:
0
</syntaxhighlight>
Using a trampoline to avoid stack overflows when k >= 20:
<
type Tramp<'t> =
| Delay of (unit -> Tramp<'t>)
Line 1,494 ⟶ 1,604:
0
</syntaxhighlight>
F# supports tail calls (when compiled in Release mode), so you can also avoid stack overflow using the straightforward approach modified to use continuation-passing style:
<syntaxhighlight lang="fsharp">
[<EntryPoint>]
let main (args : string[]) =
let k = int(args.[0])
let l x cont = cont x
let rec a k x1 x2 x3 x4 x5 cont =
if k <= 0 then
x4 (fun n4 -> x5 (fun n5 -> cont (n4+n5)))
else
let mutable k = k
let rec b cont =
k <- k - 1
a k b x1 x2 x3 x4 cont
b cont
a k (l 1) (l -1) (l -1) (l 1) (l 0) (printfn "%d")
0
</syntaxhighlight>
=={{header|Fantom}}==
Fantom has closures, so:
<syntaxhighlight lang="fantom">
class ManOrBoy
{
Line 1,514 ⟶ 1,648:
}
}
</syntaxhighlight>
yields
Line 1,520 ⟶ 1,654:
-67
</pre>
=={{header|Forth}}==
Line 1,527 ⟶ 1,660:
Gforth provides flat closures [{: ... :}L ... ;] that are initialized from the stack. You have to perform flat-closure conversion and assignment conversion manually (and this has been done here).
<
k @ 0<= IF x4 x5 f+ ELSE
B k x1 x2 x3 action-of x4 [{: B k x1 x2 x3 x4 :}L
Line 1,533 ⟶ 1,666:
k @ B @ x1 x2 x3 x4 A ;] dup B !
execute THEN ;
10 [: 1e ;] [: -1e ;] 2dup swap [: 0e ;] A f. </
=={{header|Fortran}}==
Fortran 2008 (uses an internal procedure as function argument). Tested with g95 and gfortran 4.6.
<
implicit none
Line 1,592 ⟶ 1,725:
use man_or_boy
write (*,*) A(10,one,minus_one,minus_one,one,zero)
end program test</
=={{header|Go}}==
<
import "fmt"
Line 1,613 ⟶ 1,746:
x := func(i int) func() int { return func() int { return i } }
fmt.Println(a(10, x(1), x(-1), x(-1), x(1), x(0)))
}</
Another version that uses named result parameters the way the original Algol uses the function name. This includes B setting the result of its enclosing A.
<
import "fmt"
Line 1,640 ⟶ 1,773:
fmt.Println(A(10, K(1), K(-1), K(-1), K(1), K(0)))
}
</syntaxhighlight>
By exploiting interfaces, one can more closely parallel the original Algol's polymorphic parameters.
<
import "fmt"
Line 1,676 ⟶ 1,809:
func main() {
fmt.Println(A(10, 1, -1, -1, 1, 0))
}</
Inspired by D's "faster" version, here's another that uses a different algorithm to compute the result.
<
import (
Line 1,687 ⟶ 1,820:
func A(k int) *big.Int {
if k < 6 {
var x1, x2, x3, x4 int64 = 1, -1, -1, 1
c1 := []int64{0, 0, 0, 1, 2, 3}[k]
c2 := []int64{0, 0, 1, 1, 1, 2}[k]
c3 := []int64{0, 1, 1, 0, 0, 1}[k]
c4 := []int64{1, 1, 0, 0, 0, 0}[k]
t := c1*x1 + c2*x2 + c3*x3 + c4*x4
return big.NewInt(t)
}
one := big.NewInt(1)
c0 := big.NewInt(3)
Line 1,712 ⟶ 1,854:
func main() {
for i := 0; i < 40; i++ {
p(
}
p(500)
p(10000)
p(1e6)
}</
{{out}}
<pre>
A(0) = 1
A(1) = 0
A(2) = -2
A(3) = 0
A(4) = 1
A(5) = 0
A(6) = 1
A(7) = -1
A(8) = -10
A(9) = -30
A(10) = -67
A(11) = -138
A(12) = -291
A(13) = -642
A(14) = -1446
A(15) = -3250
A(16) = -7244
A(17) = -16065
A(18) = -35601
A(19) = -78985
A(20) = -175416
A(21) = -389695
A(22) = -865609
A(23) = -1922362
A(24) = -4268854
A(25) = -9479595
A(26) = -21051458
A(27) = -46750171
A(28) = -103821058
A(29) = -230560902
A(30) = -512016658
A(31) = -1137056340
A(32) = -2525108865
A(33) = -5607619809
A(34) = -12453091089
A(35) = -27655133488
A(36) = -61414977599
A(37) = -136386945105
A(38) = -302880491178
A(39) = -672620048590
A(500) = -36608...67320 (172 digits)
A(10000) = -19928...34899 (3464 digits)
Line 1,733 ⟶ 1,914:
This is not stictly identical with Wirth's example.
<
var k = in_k
var B(): int // B is a function variable
Line 1,742 ⟶ 1,923:
return k<=0 ? x4()+x5() : B()
}
print(A(10, \ -> 1, \ -> -1, \ -> -1, \ -> 1, \ -> 0))</
Output:
Line 1,751 ⟶ 1,932:
=={{header|Groovy}}==
Solution:
<
def b; b = {
a (--k, b, x1, x2, x3, x4)
Line 1,758 ⟶ 1,939:
}
def x = { n -> { it -> n } }</
Test 1:
<
This test overflowed the stack at the default stack size. On my system I required "-Xss1409k" or larger to run successfully.
Line 1,769 ⟶ 1,950:
Test 2:
<
printf ("%3d: %7d\n", k, a(k, x(1), x(-1), x(-1), x(1), x(0)))
}</
This test required "-Xss345m" to avoid overflow.
Line 1,802 ⟶ 1,983:
Haskell is a pure language, so the impure effects of updating ''k'' must be wrapped in the IO or ST [[Monads|monad]]:
<
a
Line 1,814 ⟶ 1,994:
a k b x1 x2 x3 x4
if k <= 0
then
else b
where
Line 1,822 ⟶ 2,002:
main = a 10 # 1 # (-1) # (-1) # 1 # 0 >>= print
where
( # ) f = f . return</
On an AMD Opteron 6282 SE using GHC 7.8.2 this program can compute ''k'' = 30 in 1064 s and 156.2 GiB.
Line 1,868 ⟶ 2,048:
The co-expression version.
<
# ... be obvious when we break normal scope rules
procedure main(arglist) # supply the initial k value
Line 1,890 ⟶ 2,070:
k.value -:= 1 # diddle A's copy of k
return A(k.value, create |B(k,x1,x2,x3,x4,x5),x1,x2,x3,x4) # call A with a new k and 5 x's
end</
Below are the code changes for the non-co-expression version. A new record type is introduced and the two return expressions are changed slightly.
<
procedure eval(ref) # evaluator to distinguish between a simple value and a code reference
Line 1,903 ⟶ 2,083:
k.value -:= 1 # diddle A's copy of k
return A(k.value, defercall(B,[k,x1,x2,x3,x4,x5]),x1,x2,x3,x4)# call A with a new k and 5 x's
end</
=={{
Io is nothing if not aggressively manly.
<
a := method(k, xs,
Line 1,922 ⟶ 2,102:
1 to(500) foreach(k,
(k .. " ") print
a(k, list(1, -1, -1, 1, 0) map (x, f(x))) println)</
=={{header|J}}==
Line 1,928 ⟶ 2,108:
Given
<
L=.cocreate'' NB. L is context where names are defined.
k__L=:x
Line 1,940 ⟶ 2,120:
k__L=:k__L-1
a__L=:k__L A L&B`(x1__L f.)`(x2__L f.)`(x3__L f.)`(x4__L f.)
)</
<
_67</
=={{header|Java}}==
Line 1,952 ⟶ 2,132:
Java Version 8 and up
<
public class ManOrBoy {
Line 1,972 ⟶ 2,152:
System.out.println(A(10, () -> 1.0, () -> -1.0, () -> -1.0, () -> 1.0, () -> 0.0));
}
}</
Java Version 7
<
interface Arg {
public int run();
Line 2,002 ⟶ 2,182:
System.out.println(A(10, C(1), C(-1), C(-1), C(1), C(0)));
}
}</
=={{header|JavaScript}}==
In Chrome we get a "Maximum call stack size exceeded" when a > 13. In Firefox we get "too much recursion" when a > 12.
<
function b() {
k -= 1;
Line 2,020 ⟶ 2,200:
};
}
alert(a(10, x(1), x(-1), x(-1), x(1), x(0)));</
Implemented using ES6 syntax
<
var a = (k, x1, x2, x3, x4, x5) => {
var b = () =>
return (k > 0) ? b() : x4() + x5();
};</
=={{header|Jsish}}==
From Javascript entry.
<
/* As noted, needs a fair sized stack depth, default is 200 in jsish v2.8.24 */
Interp.conf({maxDepth:2048});
Line 2,057 ⟶ 2,237:
-67
=!EXPECTEND!=
*/</
{{out}}
Line 2,066 ⟶ 2,246:
=={{header|Julia}}==
<
b = ()-> a(k-=1, b, x1, x2, x3, x4);
k <= 0 ? (x4() + x5()) : b();
end
println(a(10, ()->1, ()->-1, ()->-1, ()->1, ()->0));</
=={{header|Kotlin}}==
Using the default JVM stack size, could only get to k = 12 before experiencing an overflow:
<
typealias Func = () -> Int
Line 2,091 ⟶ 2,271:
}
}
</syntaxhighlight>
{{out}}
Line 2,112 ⟶ 2,292:
=={{header|Lox}}==
<
print k;
fun B() {
Line 2,129 ⟶ 2,309:
fun I_1() { return -1; }
print A(10, I1, I_1, I_1, I1, I0);</
=={{header|Lua}}==
<
local function b()
k = k - 1
Line 2,147 ⟶ 2,327:
end
print(a(10, K(1), K(-1), K(-1), K(1), K(0)))</
=={{header|Mathematica}}/{{header|Wolfram Language}}==
This ''Mathematica'' code was derived from the Ruby example appearing below.
<syntaxhighlight lang="mathematica">$RecursionLimit = 1665; (* anything less fails for k0 = 10 *)
a[k0_, x1_, x2_, x3_, x4_, x5_] := Module[{k, b },
k = k0;
b = (k--; a[k, b, x1, x2, x3, x4]) &;
If[k <= 0, x4[] + x5[], b[]]]
a[10, 1 &, -1 &, -1 &, 1 &, 0 &]</syntaxhighlight>
{{out}}
<pre>-67</pre>
=={{header|Modula-3}}==
<
IMPORT IO;
Line 2,192 ⟶ 2,370:
IO.PutInt(A(10, F1, Fn1, Fn1, F1, F0));
IO.Put("\n");
END Main.</
=={{header|Nim}}==
With standard compilation values, it is possible to run the program with <code>k = 10</code>. With <code>k = 11</code>, we reach the default call depth limit (2000). In this case, compiling with option <code>-d:nimCallDepthLimit=2100</code> is enough to get the result: -138.
<syntaxhighlight lang="nim">import sugar
proc a(k: int; x1, x2, x3, x4, x5: proc(): int): int =
Line 2,205 ⟶ 2,384:
else: b()
echo a(10, () => 1, () => -1, () => -1, () => 1, () => 0)</
{{out}}
<pre>-67</pre>
=={{header|Objeck}}==
Using anonymous classes instead of closures
<syntaxhighlight lang="objeck">interface Arg {
method : virtual : public : Run() ~ Int;
}
class ManOrBoy {
New() {}
function : A(mb : ManOrBoy, k : Int, x1 : Arg, x2 : Arg, x3 : Arg, x4 : Arg, x5 : Arg) ~ Int {
if(k <= 0) {
return x4->Run() + x5->Run();
};
return Base->New(mb, k, x1, x2, x3, x4) implements Arg {
@mb : ManOrBoy; @k : Int; @x1 : Arg; @x2 : Arg; @x3 : Arg; @x4 : Arg; @m : Int;
New(mb : ManOrBoy, k : Int, x1 : Arg, x2 : Arg, x3 : Arg, x4 : Arg) {
@mb := mb; @k := k; @x1 := x1; @x2 := x2; @x3 := x3; @x4 := x4; @m := @k;
}
method : public : Run() ~ Int {
@m -= 1;
return @mb->A(@mb, @m, @self, @x1, @x2, @x3, @x4);
}
}->Run();
}
function : C(i : Int) ~ Arg {
return Base->New(i) implements Arg {
@i : Int;
New(i : Int) {
@i := i;
}
method : public : Run() ~ Int {
return @i;
}
};
}
function : Main(args : String[]) ~ Nil {
mb := ManOrBoy->New();
mb->A(mb, 10, C(1), C(-1), C(-1), C(1), C(0))->PrintLine();
}
}
</syntaxhighlight>
=={{header|Objective-C}}==
{{works with|Cocoa|Mac OS X 10.6+}}
<
typedef NSInteger (^IntegerBlock)(void);
Line 2,233 ⟶ 2,463:
}
return 0;
}</
Without ARC, the above should be:
<
typedef NSInteger (^IntegerBlock)(void);
Line 2,259 ⟶ 2,489:
[pool drain];
return 0;
}</
without Blocks or ARC:
<
-(NSInteger)call;
@end
Line 2,335 ⟶ 2,565:
[pool release];
return 0;
}</
=={{header|OCaml}}==
Line 2,389 ⟶ 2,571:
OCaml variables are not mutable, so "k" is wrapped in a mutable object, which we access through a reference type called "ref".
<
if k <= 0 then
x4 () + x5 ()
Line 2,401 ⟶ 2,583:
let () =
Printf.printf "%d\n" (a 10 (fun () -> 1) (fun () -> -1) (fun () -> -1) (fun () -> 1) (fun () -> 0))</
=={{header|Odin}}==
{{trans|C}}
Odin does not have [[closures]], so we emulate them by copying the C example.
<syntaxhighlight lang="odin">
package main
import "core:fmt"
import "core:os"
import "core:strconv"
Arg :: struct {
fn : proc (^Arg) -> int,
k : ^int,
x1, x2, x3, x4, x5 : ^Arg,
}
B :: proc (a : ^Arg) -> int {
a.k^ -= 1
k := a.k^
return A(&Arg { fn = B, k = &k, x1 = a, x2 = a.x1, x3 = a.x2, x4 = a.x3, x5 = a.x4 } )
}
A :: proc (a : ^Arg) -> int {
return a.x4->fn() + a.x5->fn() if a.k^ <= 0 else B(a)
}
main :: proc () {
f_1 :: proc (^Arg) -> int { return -1 }
f0 :: proc (^Arg) -> int { return 0 }
f1 :: proc (^Arg) -> int { return 1 }
k := strconv.atoi(os.args[1]) if len(os.args) == 2 else 10
fmt.println(A(&Arg { fn = B, k = &k, x1 = &Arg { fn = f1 }, x2 = &Arg { fn = f_1 }, x3 = &Arg { fn = f_1 }, x4 = &Arg { fn = f1 }, x5 = &Arg { fn = f0 } }))
}
</syntaxhighlight>
=={{header|Ol}}==
Line 2,408 ⟶ 2,627:
But! For some reasons in version 1.2 a very limited mutators (set-ref!, set-car!, set-cdr!) are added; so this task can be implemented as usual. Please, be aware that mutators receives only values (small numbers, constants) or previously (before the mutating dest) declared objects.
<
; Because argument "k" is a small number, it's a value, not an object.
; So we must 'pack' it in object - 'box' it; And 'unbox' when we try to get value.
Line 2,436 ⟶ 2,655:
(print (man-or-boy 15))
(print (man-or-boy 20))
</syntaxhighlight>
Output:
<pre>
Line 2,443 ⟶ 2,662:
-175416
</pre>
=={{header|Oz}}==
Line 2,452 ⟶ 2,670:
We use explicit "return variables" to emulate the strange behaviour of the ALGOL B procedure which assigns a value to A's return value.
<
fun {A K X1 X2 X3 X4 X5}
ReturnA = {NewCell undefined}
Line 2,472 ⟶ 2,690:
end
in
{Show {A {NewCell 10} {C 1} {C ~1} {C ~1} {C 1} {C 0}}}</
=={{header|Pascal}}==
<
function zero: integer; begin zero := 0 end;
Line 2,500 ⟶ 2,718:
begin writeln(A(10, one, negone, negone, one, zero))
end.</
=={{header|Perl}}==
<
my ($k, $x1, $x2, $x3, $x4, $x5) = @_;
my($B);
Line 2,510 ⟶ 2,728:
}
print A(10, sub{1}, sub {-1}, sub{-1}, sub{1}, sub{0} ), "\n";</
<!-- $B must be declared before it is used. Otherwise it references the global variable
$B.
Line 2,516 ⟶ 2,734:
print A(10, map {my $p = \$_; sub{$$p}} 1, -1, -1, 1, 0), "\n";
-->
=={{header|Phix}}==
Ugh. Phix does not allow this sort of nonsense implicitly, so you have to get a bit <s>dirty</s> creative.<br>
Explicitly allocates space (which is automatically freed) for the various "k contexts". Manages up to k=23 in about 10s, but crashes on k=24.
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- allocate()</span>
<span style="color: #008080;">forward</span> <span style="color: #008080;">function</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">object</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">kptr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x4</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peek4s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">kptr</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span>
<span style="color: #7060A8;">poke4</span><span style="color: #0000FF;">(</span><span style="color: #000000;">kptr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">kptr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x4</span><span style="color: #0000FF;">},</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x4</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">object</span> <span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x4</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">B</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x4</span><span style="color: #0000FF;">):</span><span style="color: #000000;">x4</span><span style="color: #0000FF;">)+</span>
<span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x5</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">B</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x5</span><span style="color: #0000FF;">):</span><span style="color: #000000;">x5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">kptr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">poke4</span><span style="color: #0000FF;">(</span><span style="color: #000000;">kptr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">B</span><span style="color: #0000FF;">({</span><span style="color: #000000;">kptr</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x4</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">23</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"A(%d) = %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">k</span><span style="color: #0000FF;">,</span><span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
A(0) = 1
A(1) = 0
A(3) = 0
A(4) = 1
A(5) = 0
A(6) = 1
A(11) = -138
A(12) = -291
A(13) = -642
A(14) = -1446
A(15) = -3250
A(16) = -7244
A(17) = -16065
A(18) = -35601
A(19) = -78985
A(20) = -175416
A(21) = -389695
A(22) = -865609
A(23) = -1922362
</pre>
While the above will not run under pwa/p2js, the following translation of <del>D (Faster Version)</del> Go is fine, and rather fast.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">first5</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;"><</span><span style="color: #000000;">5</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">first5</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">c0</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c3</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">c3</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c0</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #000000;">c0</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c1</span>
<span style="color: #000000;">c1</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c2</span>
<span style="color: #000000;">c2</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c3</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c0</span><span style="color: #0000FF;">-</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c3</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">40</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">k</span><span style="color: #0000FF;">,</span><span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
...
10 -67
...
20 -175416
...
30 -512016658
...
40 -1493716995219
</pre>
And the same converted to use gmp:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;"><</span><span style="color: #000000;">5</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">c0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">c1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">c2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">c3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">to</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_sub_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">mpz_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c2</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c3</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)&{</span><span style="color: #000000;">30</span><span style="color: #0000FF;">,</span><span style="color: #000000;">39</span><span style="color: #0000FF;">,</span><span style="color: #000000;">500</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10000</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1e6</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)-(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"A(%,d) = %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">mpz_get_short_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">A</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]))})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
A(0) = 1
A(1) = 0
A(2) = -2
A(3) = 0
A(4) = 1
A(5) = 0
A(6) = 1
A(7) = -1
A(8) = -10
A(9) = -30
A(10) = -67
A(11) = -138
A(12) = -291
A(13) = -642
A(14) = -1446
A(15) = -3250
A(16) = -7244
A(17) = -16065
A(18) = -35601
A(19) = -78985
A(20) = -175416
A(30) = -512016658
A(39) = -672620048590
A(500) = -36608736847739011154...32375404781872267320 (172 digits)
A(10,000) = -19928164276191803466...30409380127296034899 (3,464 digits)
A(1,000,000) = -67341136870269950723...54621754484081195219 (346,497 digits)
</pre>
The 1e6 works fine under pwa/p2js but takes/causes a blank screen for 3 mins, compared to 45s for desktop/Phix, and 29s for the Go version.
=={{header|PHP}}==
{{works with|PHP|5.3+}}
<
function A($k,$x1,$x2,$x3,$x4,$x5) {
$b = function () use (&$b,&$k,$x1,$x2,$x3,$x4) {
Line 2,584 ⟶ 2,895:
function () { return 1; },
function () { return 0; }) . "\n";
?></
{{works with|PHP|pre-5.3 and 5.3+}}
<
function A($k,$x1,$x2,$x3,$x4,$x5) {
static $i = 0;
Line 2,608 ⟶ 2,919:
create_function('', 'return 1;'),
create_function('', 'return 0;')) . "\n";
?></
=={{header|PicoLisp}}==
As PicoLisp uses exclusively shallow dynamic binding, stack frames have to be
explicitly constructed.
<
(let (@K (cons K) B (cons)) # Explicit frame
(set B
Line 2,620 ⟶ 2,931:
(if (gt0 (car @K)) ((car B)) (+ (X4) (X5))) ) )
(a 10 '(() 1) '(() -1) '(() -1) '(() 1) '(() 0))</
Output:
<pre>-> -67</pre>
Line 2,677 ⟶ 2,988:
=={{header|Python}}==
{{works with|Python|2.5}}
<
import sys
sys.setrecursionlimit(1025)
Line 2,690 ⟶ 3,001:
x = lambda i: lambda: i
print(a(10, x(1), x(-1), x(-1), x(1), x(0)))
</syntaxhighlight>
A better-looking alternative to using lists as storage are function attributes:
<
import sys
sys.setrecursionlimit(1025)
Line 2,705 ⟶ 3,016:
x = lambda i: lambda: i
print(a(10, x(1), x(-1), x(-1), x(1), x(0)))
</syntaxhighlight>
Output:
Line 2,713 ⟶ 3,024:
{{works with|Python|3.0}}
<
import sys
sys.setrecursionlimit(1025)
Line 2,724 ⟶ 3,035:
return x4() + x5() if k <= 0 else B()
print(A(10, lambda: 1, lambda: -1, lambda: -1, lambda: 1, lambda: 0))</
=={{header|R}}==
Like many implementations this uses lambda wrappers around the numeric arguments and explicit function calls in the x4() + x5() step to force the order of evaluation and handle value/call duality.
<
A <- function(k, x1, x2, x3, x4, x5) {
Line 2,736 ⟶ 3,047:
}
A(10, n(1), n(-1), n(-1), n(1), n(0))</
That is the way any sane person would implement Man-or-Boy. However, we can be a bit more evil than that. Here <tt>call.by.name</tt> is a function that rewrites the function definition given as its input:
<
cl <- as.list(match.call())
sublist <- lapply(cl[2:(length(cl)-1)],
Line 2,754 ⟶ 3,065:
}, list(body=fndef[[3]], subcall=subcall))
eval.parent(fndef)
}</
allowing us to write A in a way that mirrors ALGOL60 semantics closely:
<
function(k, x1, x2, x3, x4, x5) {
Aout <- NULL
Line 2,768 ⟶ 3,079:
Aout
}
)</
One has to increase the recursion limit a bit, but it gives correct answers:
<
> mapply(A, 0:10, 1, -1, -1, 1, 0)
[1] 1 0 -2 0 1 0 1 -1 -10 -30 -67</
If you inspect <tt>A</tt> without the original source you will see what has happened: <tt>call.by.name</tt> rewrote A so that it looks like this:
<
function (k, x1, x2, x3, x4, x5)
{
Line 2,795 ⟶ 3,106:
x4 = substitute(evalq(., .caller), list(. = substitute(x4))),
x5 = substitute(evalq(., .caller), list(. = substitute(x5))))))
}</
That is, instead of evaluating its arguments normally, <tt>A</tt> captures their original expressions, and instead of evaluating its body normally, <tt>A</tt> substitutes calls to <tt>evalq</tt> the captured argument expressions in the calling frame. After a few levels of recursion this way, you end up evaluating expressions like <tt>A(k, B(), evalq(B(), .caller), evalq(evalq(B(), .caller), .caller), evalq(evalq(evalq(1, .caller), .caller), .caller), evalq(evalq(evalq(-1, .caller), .caller), .caller))</tt>, so this is not very efficient, but works.
Line 2,803 ⟶ 3,114:
Copied from Scheme, works fine:
<
(define (A k x1 x2 x3 x4 x5)
Line 2,813 ⟶ 3,124:
(B)))
(A 10 (lambda () 1) (lambda () -1) (lambda () -1) (lambda () 1) (lambda () 0))</
Use "named let" to define and implicitly execute B:
<syntaxhighlight lang="racket">#lang racket
(define (A k x1 x2 x3 x4 x5)
(if (<= k 0)
(+ (x4) (x5))
(let B ()
(set! k (- k 1))
(A k B x1 x2 x3 x4))))
(A 10 (lambda () 1) (lambda () -1) (lambda () -1) (lambda () 1) (lambda () 0))</syntaxhighlight>
=={{header|Raku}}==
(formerly Perl 6)
This solution avoids creating the closure B if $k <= 0 (that is, nearly every time).
<syntaxhighlight lang="raku" line>sub A($k is copy, &x1, &x2, &x3, &x4, &x5) {
$k <= 0
?? x4() + x5()
!! (my &B = { A(--$k, &B, &x1, &x2, &x3, &x4) })();
};
say A(10, {1}, {-1}, {-1}, {1}, {0});</syntaxhighlight>
{{out}}
<pre>-67</pre>
=={{header|REXX}}==
The REXX language only passes by value, not by name. However, there is a way to treat passed arguments as names.
<br>However, using the code below, it only works for '''n''' up to (and including) '''3'''.
<
do n=0 /*increment N from zero forever. */
say 'n='n a(N,x1,x2,x3,x4,x5) /*display the result to the terminal. */
Line 2,834 ⟶ 3,171:
x3: procedure; return -1
x4: procedure; return 1
x5: procedure; return 0</
'''output'''
<pre>
Line 2,846 ⟶ 3,183:
Note: the lambda call can be replaced with Proc.new and still work.
<
b = lambda { k -= 1; a(k, b, x1, x2, x3, x4) }
k <= 0 ? x4[] + x5[] : b[]
end
puts a(10, lambda {1}, lambda {-1}, lambda {-1}, lambda {1}, lambda {0})</
=={{header|Rust}}==
<
trait Arg {
Line 2,894 ⟶ 3,230:
pub fn main() {
println!("{}", a(10, &1, &-1, &-1, &1, &0));
}</
Another solution where we have B take itself as an argument in order to recursively call itself:
<
fn a(k: i32, x1: &Fn() -> i32, x2: &Fn() -> i32, x3: &Fn() -> i32, x4: &Fn() -> i32, x5: &Fn() -> i32) -> i32 {
Line 2,910 ⟶ 3,246:
};
let b = ||(b.f)(&b);
return if k <= 0 {x4() + x5()} else {b()}
}
pub fn main() {
println!("{}", a(10, &||1, &||-1, &||-1, &||1, &||0));
}</
Another solution that gives a reference-counted function a weak reference to itself:
{{trans|Objective-C}}
<syntaxhighlight lang="rust">use std::cell::Cell;
use std::cell::RefCell;
use std::rc::Rc;
Line 2,931 ⟶ 3,264:
let weak_holder: Rc<RefCell<Weak<Fn() -> i32>>> = Rc::new(RefCell::new(Weak::<fn() -> i32>::new()));
let weak_holder2 = weak_holder.clone();
let
let b: Rc<Fn() -> i32> = Rc::new(move || {
let b = weak_holder2.borrow().upgrade().unwrap();
return a(
});
weak_holder.replace(Rc::downgrade(&b));
return if k <= 0 {x4() + x5()} else {b()}
}
pub fn main() {
println!("{}", a(10, &||1, &||-1, &||-1, &||1, &||0));
}</
=={{header|Scala}}==
<
var k = in_k
def B: Int = {
Line 2,959 ⟶ 3,288:
if (k<=0) x4+x5 else B
}
println(A(10, 1, -1, -1, 1, 0))</
=={{header|Scheme}}==
<syntaxhighlight lang="scheme">(define (A k x1 x2 x3 x4 x5)
(define (B)
(set! k (- k 1))
(A k B x1 x2 x3 x4))
(if (<= k 0)
(+ (x4) (x5))
(B)))
(A 10 (lambda () 1) (lambda () -1) (lambda () -1) (lambda () 1) (lambda () 0))</syntaxhighlight>
=={{header|Sidef}}==
<
func b { a(--k, b, x1, x2, x3, x4) };
k <= 0 ? (x4() + x5()) : b();
}
say a(10, ->{1}, ->{-1}, ->{-1}, ->{1}, ->{0}); #=> -67</
This solution avoids creating the closure b if k <= 0 (that is, nearly every time).
<
k <= 0 ? (x4() + x5())
: func b { a(--k, b, x1, x2, x3, x4) }();
}
say a(10, ->{1}, ->{-1}, ->{-1}, ->{1}, ->{0}); #=> -67</
Alternatively, we can implement it as a class also:
<
method a(k, x1, x2, x3, x4, x5) {
func b { self.a(--k, b, x1, x2, x3, x4) };
Line 2,984 ⟶ 3,325:
var obj = MOB();
say obj.a(10, ->{1}, ->{-1}, ->{-1}, ->{1}, ->{0});</
=={{header|
Number>>x1: x1 x2: x2 x3: x3 x4: x4 x5: x5
Line 3,011 ⟶ 3,336:
10 x1: [1] x2: [-1] x3: [-1] x4: [1] x5: [0]
=={{header|Snap!}}==
[[File:snap-man-or-boy.png]]
=={{header|Sparkling}}==
Sparkling does not directly support modifying external local variables. To work around this limitation, we wrap the <tt>k</tt> variable in an array, which is mutable.
<
let kk = { "k": k.k };
let b = function b() {
Line 3,030 ⟶ 3,359:
}
print(a({ "k": 10 }, x(1), x(-1), x(-1), x(1), x(0)));</
=={{header|Standard ML}}==
Line 3,036 ⟶ 3,365:
Standard ML variables are not mutable, so "k" is wrapped in a mutable object, which we access through a reference type called "ref".
<
if k <= 0 then
x4 () + x5 ()
Line 3,050 ⟶ 3,379:
val () =
print (Int.toString (a (10, fn () => 1, fn () => ~1, fn () => ~1, fn () => 1, fn () => 0)) ^ "\n")</
=={{header|Swift}}==
Line 3,057 ⟶ 3,386:
As of Swift 3.0, closure parameters are "non-escaping" by default. The Man or Boy Test requires the closures to be escaping, and thus we must now annotate the closure parameters with the "@escaping" attribute.
<
_ x1: @escaping () -> Int,
_ x2: @escaping () -> Int,
Line 3,077 ⟶ 3,406:
}
print(A(10, {1}, {-1}, {-1}, {1}, {0}))</
{{works with|Swift|2.x}}
<
var k1 = k
func B() -> Int {
Line 3,092 ⟶ 3,421:
}
print(A(10, {1}, {-1}, {-1}, {1}, {0}))</
{{works with|Swift|1.x}}
<
var B: (() -> Int)!
B = {
Line 3,107 ⟶ 3,436:
}
println(A(10, {1}, {-1}, {-1}, {1}, {0}))</
=={{header|Tcl}}
There are two nontrivial features in the "man or boy" test. One is that the parameters ''x1'' though ''x5'' are in general going to be function calls that don't get evaluated until their values are needed for the addition in procedure A, which means that these in Tcl are going to be scripts, and therefore it is necessary to introduce a helper procedure C that returns a constant value. The other is that procedure B needs to refer to variables in the local context of its "parent" instance of procedure A. This is precisely what the '''upvar''' core command does, but the ''absolute'' target level needs to be embedded into the script that performs the delayed call to procedure B ('''upvar''' is more often used with relative levels).
<
expr {$k<=0 ? [eval $x4]+[eval $x5] : [B \#[info level]]}
}
Line 3,122 ⟶ 3,451:
proc C {val} {return $val}
interp recursionlimit {} 1157
A 10 {C 1} {C -1} {C -1} {C 1} {C 0}</
The <tt>[info level 0]</tt> here is a sort of "self" idiom; it returns the command (with arguments) that called the current procedure.
Since the values of ''x1'' through ''x4'' are never modified, it is also possible to embed these as parameters of B, thereby slightly purifying the program:
<
proc BP {level x1 x2 x3 x4} {AP [uplevel $level {incr k -1}] [info level 0] $x1 $x2 $x3 $x4}
proc C {val} {return $val}
interp recursionlimit {} 1157
AP 10 {C 1} {C -1} {C -1} {C 1} {C 0}</
=={{header|TSQL}}==
SQL is kinda limited, and TSQL is not much better. Unfortunately it fails the Man test due to Stack Level being limited to 32.
<
CREATE PROCEDURE dbo.LAMBDA_WRAP_INTEGER
Line 3,280 ⟶ 3,609:
END
</syntaxhighlight>
Outputs:
Line 3,287 ⟶ 3,616:
For k=3, result=0
For k=4, result=1
=={{header|TXR}}==
Line 3,293 ⟶ 3,621:
The goal in this solution is to emulate the Algol 60 solution as closely as possible, and not merely get the correct result. For that, we could just crib the Common Lisp or Scheme solution, with more succinct syntax, like this:
<
(labels ((B ()
(dec k)
Line 3,299 ⟶ 3,627:
(if (<= k 0) (+ [x4] [x5]) (B))))
(prinl (A 10 (ret 1) (ret -1) (ret -1) (ret 1) (ret 0)))</
To do a proper job, we define a call-by-name system as a set of functions and macros. With these, the function <code>A</code> can be defined as a close transliteration of the Algol, as can the call to <code>A</code> with the integer constants:
<
(let ((k k))
(labels-cbn (B ()
Line 3,312 ⟶ 3,640:
(B))))) ;; value of (B) correctly discarded here!
(prinl (A 10 1 -1 -1 1 0))</
We define the global function with <code>defun-cbn</code> ("cbn" stands for "call by name") and the inner function with <code>labels-cbn</code>. These functions are actually macros which call hidden call-by-value functions. The macros create all the necessary thunks out of their argument expressions, and the hidden functions use local macros to provide transparent access to their arguments from their bodies.
Line 3,324 ⟶ 3,652:
The complete code follows:
<
(defmacro make-cbn-val (place)
Line 3,391 ⟶ 3,719:
(B))))) ;; value of (B) correctly discarded here!
(prinl (A 10 1 -1 -1 1 0))</
=={{header|Visual Prolog}}
Visual Prolog (like any other Prolog) does not allow variables to be changed. But behavior can easily be mimicked by using a '''varM''' (modifiable variable), which is actually an object containing a value of the relevant type in a modifiable entity (a so called fact variable). Secondly, anonymous function (lambda-expression) cannot be recursive, but this is mimicked by using yet a '''varM''' to hold the function.
Line 3,399 ⟶ 3,727:
(Token coloring of Visual Prolog in this wiki is unfortunately wrong, because styles are used across languages. A correctly colored version can be seen in [http://wiki.visual-prolog.com/index.php?title=Man_or_boy_test Man or boy test] in the Visual Prolog wiki).
<syntaxhighlight lang="visualprolog">
implement main
open core
Line 3,421 ⟶ 3,749:
R = if KM:value <= 0 then X4() + X5() else BM:value() end if.
end implement main</
=={{header|Vorpal}}
Adapted from the Lua example. In vorpal, all execution is a message to an object. This task primarily involves functions, so we have the apply the function objects to self for them to execute. Correctly, prints -67.
<
b = method(){
code.k = code.k - 1
Line 3,454 ⟶ 3,782:
}
self.a(10, self.K(1), self.K(-1), self.K(-1), self.K(1), self.K(0)).print()</
=={{header|Wren}}==
===CLI===
In Wren, a fiber's stack starts quite small but is then increased as needed, apparently limited only by available memory. Anyway, satisfying the test for k up to 20 is unlikely to be a problem on a modern machine.
<syntaxhighlight lang="wren">import "./fmt" for Fmt
var a
a = Fn.new { |k, x1, x2, x3, x4, x5|
var b
b = Fn.new {
k = k - 1
return a.call(k, b, x1, x2, x3, x4)
}
return (k <= 0) ? x4.call() + x5.call() : b.call()
}
System.print(" k a")
for (k in 0..20) {
Fmt.print("$2d : $ d", k, a.call(k, Fn.new { 1 }, Fn.new { -1 }, Fn.new { -1 }, Fn.new { 1 }, Fn.new { 0 }))
}</syntaxhighlight>
{{out}}
<pre>
k a
0 : 1
1 : 0
2 : -2
3 : 0
4 : 1
5 : 0
6 : 1
7 : -1
8 : -10
9 : -30
10 : -67
11 : -138
12 : -291
13 : -642
14 : -1446
15 : -3250
16 : -7244
17 : -16065
18 : -35601
19 : -78985
20 : -175416
</pre>
===Embedded (GMP)===
{{libheader|Wren-gmp}}
{{libheader|Wren-fmt}}
Based on Go's 'faster' version this runs in about 15.2 seconds which (surprisingly) is slightly faster than Go itself (16.6 seconds).
<syntaxhighlight lang="wren">/* Man_or_boy_test_2.wren */
import "./gmp" for Mpz
import "./fmt" for Fmt
var A = Fn.new { |k|
if (k < 6) {
var x1 = 1
var x2 = -1
var x3 = -1
var x4 = 1
var c1 = [0, 0, 0, 1, 2, 3][k]
var c2 = [0, 0, 1, 1, 1, 2][k]
var c3 = [0, 1, 1, 0, 0, 1][k]
var c4 = [1, 1, 0, 0, 0, 0][k]
return c1*x1 + c2*x2 + c3*x3 + c4*x4
}
var one = Mpz.one
var c0 = Mpz.three
var c1 = Mpz.two
var c2 = Mpz.one
var c3 = Mpz.zero
for (j in 5...k) {
c3.add(c0).sub(one)
c0.add(c1)
c1.add(c2)
c2.add(c3)
}
return c0.add(c0.sub(c0.sub(c1), c2), c3)
}
var p = Fn.new { |k|
Fmt.write("A($d) = ", k)
var s = A.call(k).toString
if (s.count < 60) {
System.print(s)
} else {
Fmt.print("$s...$s ($d digits)", s[0..5], s[-5..-1], s.count - 1)
}
}
for (i in 0..39) p.call(i)
p.call(500)
p.call(10000)
p.call(1e6) </syntaxhighlight>
{{out}}
<pre>
Same as Go 'faster' version.
</pre>
=={{header|Zig}}==
'''Works with:''' 0.10.x, 0.11.x, 0.12.0-dev.1390+94cee4fb2
<syntaxhighlight lang="zig">const Record = struct {
yieldFn: *const fn (record: *Record) i32,
k: *i32 = undefined,
x1: *Record = undefined,
x2: *Record = undefined,
x3: *Record = undefined,
x4: *Record = undefined,
x5: *Record = undefined,
inline fn run(record: *Record) i32 {
return record.yieldFn(record);
}
pub fn A(record: *Record) i32 {
return if (record.k.* <= 0)
record.x4.run() + record.x5.run()
else
record.B();
}
fn B(record: *Record) i32 {
record.k.* -= 1;
var k_copy_on_stack: i32 = record.k.*;
var b: Record = .{
.yieldFn = &Record.B,
.k = &k_copy_on_stack,
.x1 = record,
.x2 = record.x1,
.x3 = record.x2,
.x4 = record.x3,
.x5 = record.x4,
};
return b.A();
}
};
const numbers = struct {
fn positiveOne(unused_record: *Record) i32 {
_ = unused_record;
return 1;
}
fn zero(unused_record: *Record) i32 {
_ = unused_record;
return 0;
}
fn negativeOne(unused_record: *Record) i32 {
_ = unused_record;
return -1;
}
};
const std = @import("std");
pub fn main() void {
var i: u31 = 0;
while (i <= 31) : (i += 1) {
var k: i32 = i;
var @"+1_record": Record = .{ .yieldFn = &numbers.positiveOne };
var @"0_record": Record = .{ .yieldFn = &numbers.zero };
var @"-1_record": Record = .{ .yieldFn = &numbers.negativeOne };
var record: Record = .{
.yieldFn = &Record.B,
.k = &k,
.x1 = &@"+1_record",
.x2 = &@"-1_record",
.x3 = &@"-1_record",
.x4 = &@"+1_record",
.x5 = &@"0_record",
};
std.debug.print("[{d:>3}] = {d}\n", .{ i, record.A() });
}
}</syntaxhighlight>
{{out}}
<pre>
$ zig build-exe -OReleaseSmall -fstrip src/man_or_boy_test.zig
$ ulimit -s
8192
$ ./man_or_boy_test
[ 0] = 1
[ 1] = 0
[ 2] = -2
[ 3] = 0
[ 4] = 1
[ 5] = 0
[ 6] = 1
[ 7] = -1
[ 8] = -10
[ 9] = -30
[ 10] = -67
[ 11] = -138
[ 12] = -291
[ 13] = -642
[ 14] = -1446
[ 15] = -3250
[ 16] = -7244
[ 17] = -16065
[ 18] = -35601
[1] 22315 segmentation fault ./man_or_boy_test
$ ulimit -s 71296
$ ./man_or_boy_test
[ 0] = 1
[ 1] = 0
[ 2] = -2
[ 3] = 0
[ 4] = 1
[ 5] = 0
[ 6] = 1
[ 7] = -1
[ 8] = -10
[ 9] = -30
[ 10] = -67
[ 11] = -138
[ 12] = -291
[ 13] = -642
[ 14] = -1446
[ 15] = -3250
[ 16] = -7244
[ 17] = -16065
[ 18] = -35601
[ 19] = -78985
[ 20] = -175416
[1] 22384 segmentation fault ./man_or_boy_test
</pre>
=={{header|zkl}}
The compiler is OK but the VM is a girlie-man VM. Due to the way closures are built, the stack blows quickly when closures recurse. So, while the code can be written per Knuth, it is unable to do anything. So, classes are used to simulate the closures. Also (5)()-->5 so no problems there.
<
B:=CB(k, x1, x2, x3, x4, x5);
if(k <= 0) x4()+x5() else B.B();
Line 3,473 ⟶ 4,040:
A(k, B, x1, x2, x3, x4);
}
}</
{{out}}
<pre>
|