#!perl6
use v6;

# This test demonstrates the use of perl 6 multi-subs to 
# mimic the pattern matching style of functional programming
# languages. 

multi sub length ()          returns Int { 0               }
multi sub length (*$x, *@xs) returns Int { 1 + length(@xs) }

say "... length";
say length(1, 'foo', 3, 4, 'bar'); 
say length('foo');            
# say length();

multi sub sum ()          returns Int { 0             }
multi sub sum (*$x, *@xs) returns Int { $x + sum(@xs) }

say "... sum";
say sum(1 .. 10);
say sum(1 .. 5);
say sum(2, 2, 2, 2);

sub is_even (Int $val) returns Bool { ($val <= 0) ?? 1 :: is_odd($val - 1)  }
sub is_odd  (Int $val) returns Bool { ($val <= 0) ?? 0 :: is_even($val - 1) }

say "... mutually recursive even and odd predicates";
say is_even(4);
say is_odd(4);
say is_even(5);
say is_odd(5);

multi sub reverse ()          { ()                 }
multi sub reverse (*$x, *@xs) { (reverse(@xs), $x) }

say "... reverse";
my @result = reverse(1, 'foo', 3, 4, 'bar');
say join ", ", @result; 

my @result = reverse('foo');            
say join ", ", @result; 

# my @result = reverse();
# say join ", ", @result; 

multi sub member (*$val)            returns Bool { 0 }
multi sub member (*$val, *$x, *@xs) returns Bool { ($val eq $x) || member($val, @xs) }

say "... member";
say member('foo', 1, 'foo', 3, 4, 'bar'); 
say member('baz', 1, 'foo', 3, 4, 'bar');
say member('bar', 1, 'foo', 3, 4, 'bar');           

multi sub unique ()          { () }
multi sub unique (*$x, *@xs) { member($x, @xs) ?? unique(@xs) :: ($x, unique(@xs)) }

say "... unique";
my @result = unique('foo', 5, 4, 3, 3, 3, 3, 1, 'foo', 3, 4, 'bar'); 
say join ", ", @result;

my @result = unique(1, 2, 3, 4, 1, 2, 3, 2, 2, 1, 1, 1, 1, 2, 4, 1, 1); 
say join ", ", @result;

my @result = unique(1, 1, 1, 1, 1, 1, 1, 1); 
say join ", ", @result;

my @result = unique('foo'); 
say join ", ", @result;

# my @result = unique(); 
# say join ", ", @result;