add begin.t from Method::Signatures
[p5sagit/Function-Parameters.git] / t / recursion.t
1 #!perl
2 use warnings FATAL => 'all';
3 use strict;
4
5 use Test::More tests => 26;
6
7 use Function::Parameters qw(:strict);
8
9 fun foo_r($depth, $fst, $snd) {
10         return [$fst, $snd, $snd - $fst] if $depth <= 0;
11         $fst++;
12         my $thd = foo_r $depth - 1, $fst + $snd, $fst * $snd;
13         $snd++;
14         return [$fst, $snd, $thd];
15 }
16
17 fun foo_o($depth, $fst = 1, $snd = 2) {
18         return [$fst, $snd, $snd - $fst] if $depth <= 0;
19         $fst++;
20         my $thd = foo_o $depth - 1, $fst + $snd, $fst * $snd;
21         $snd++;
22         return [$fst, $snd, $thd];
23 }
24
25 fun foo_nr(:$depth, :$fst, :$snd) {
26         return [$fst, $snd, $snd - $fst] if $depth <= 0;
27         $fst++;
28         my $thd = foo_nr snd => $fst * $snd, depth => $depth - 1, fst => $fst + $snd;
29         $snd++;
30         return [$fst, $snd, $thd];
31 }
32
33 fun foo_no(:$depth, :$fst = 1, :$snd = 2) {
34         return [$fst, $snd, $snd - $fst] if $depth <= 0;
35         $fst++;
36         my $thd = foo_no snd => $fst * $snd, depth => $depth - 1, fst => $fst + $snd;
37         $snd++;
38         return [$fst, $snd, $thd];
39 }
40
41 for my $f (
42         \&foo_r, \&foo_o,
43         map { my $f = $_; fun ($d, $x, $y) { $f->(depth => $d, snd => $y, fst => $x) } }
44         \&foo_nr, \&foo_no
45 ) {
46         is_deeply $f->(0, 3, 5), [3, 5, 2];
47         is_deeply $f->(1, 3, 5), [4, 6, [9, 20, 11]];
48         is_deeply $f->(2, 3, 5), [4, 6, [10, 21, [30, 200, 170]]];
49 }
50
51 fun slurpy(:$n, %rest) { [$n, \%rest] }
52
53 {
54         is_deeply slurpy(a => 1, b => 2, n => 9), [9, {a => 1, b => 2}];
55         my $sav1 = slurpy(n => 5);
56         is_deeply $sav1, [5, {}];
57         my $sav2 = slurpy(n => 6, a => 3);
58         is_deeply $sav2, [6, {a => 3}];
59         is_deeply $sav1, [5, {}];
60         is_deeply slurpy(b => 4, n => 7, hello => "world"), [7, {hello => "world", b => 4}];
61         is_deeply $sav1, [5, {}];
62         is_deeply $sav2, [6, {a => 3}];
63 }
64
65 {
66         {
67                 package TimelyDestruction;
68
69                 method new($class: $f) {
70                         bless {on_destroy => $f}, $class
71                 }
72
73                 method DESTROY {
74                         $self->{on_destroy}();
75                 }
76         }
77
78         use Function::Parameters; # lax
79
80         fun bar(:$n) { defined $n ? $n + 1 : "nope" }
81
82         is bar(n => undef), "nope";
83         is bar(n => 2), 3;
84         is bar, "nope";
85
86         my $dead = 0;
87         {
88                 my $o = TimelyDestruction->new(fun () { $dead++ });
89                 is bar(n => $o), $o + 1, "this juice is bangin yo";
90         }
91         is $dead, 1;
92         $dead = 999;
93         is bar(n => 3), 4;
94         is $dead, 999;
95 }