File: reduce.t

package info (click to toggle)
libautobox-list-util-perl 20090629-3
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 116 kB
  • ctags: 12
  • sloc: perl: 59; makefile: 2
file content (105 lines) | stat: -rwxr-xr-x 2,528 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use blib;
use strict;
use autobox::List::Util;
use Test::More tests => 19;

my $v = []->reduce(sub {});

is( $v,	undef,	'no args');

$v = [756,3,7,4]->reduce(sub { $a / $b });
is( $v,	9,	'4-arg divide');

$v = [6]->reduce( sub { $a / $b } );
is( $v,	6,	'one arg');

my @a = map { rand } 0 .. 20;
$v = @a->reduce( sub { $a < $b ? $a : $b });
is( $v,	@a->min,	'min');

@a = map { pack("C", int(rand(256))) } 0 .. 20;
$v = @a->reduce( sub { $a . $b } );
is( $v,	join("",@a),	'concat');

sub add {
  my($aa, $bb) = @_;
  return $aa + $bb;
}

$v = [3, 2, 1]->reduce( sub { my $t="$a $b\n"; 0+add($a, $b) } );
is( $v,	6,	'call sub');

# Check that eval{} inside the block works correctly
$v = [0,1,2,3,4]->reduce( sub { eval { die }; $a + $b } );
is( $v,	10,	'use eval{}');

$v = !defined eval { [0..4]->reduce( sub { die if $b > 2; $a + $b } ) };
ok($v, 'die');

sub foobar { [0..3]->reduce( sub { (defined(wantarray) && !wantarray) ? $a+1 : 0 } ) }
($v) = foobar();
is( $v,	3,	'scalar context');

sub add2 { $a + $b }

$v = [1,2,3]->reduce(\&add2);
is( $v,	6,	'sub reference');

$v = [3,4,5]->reduce(sub { add2() });
is( $v, 12,	'call sub');


$v = [1,2,3]->reduce( sub { eval "$a + $b" } );
is( $v, 6, 'eval string');

$a = 8; $b = 9;
$v = [1,2,3]->reduce(sub { $a * $b });
is( $a, 8, 'restore $a');
is( $b, 9, 'restore $b');


# Can we leave the sub with 'return'?
$v = [2,4,6]->reduce( sub {return $a+$b} );
is($v, 12, 'return');

# ... even in a loop?
$v = [2,4,6]->reduce(sub {while(1) {return $a+$b} });
is($v, 12, 'return from loop');


# Does it work from another package?
# FIXME: this doesn't work
#{ 
#	package Foo;
#	$a = $b;
#	::is([1..4]->reduce( sub {$a*$b} ), 24, 'other package');
#}


# Can we undefine a reduce sub while it's running?
sub self_immolate {undef &self_immolate; 1}
eval { $v = [1,2]->reduce(\&self_immolate) };
like($@, qr/^Can't undef active subroutine/, "undef active sub");

# Redefining an active sub should not fail, but whether the
# redefinition takes effect immediately depends on whether we're
# running the Perl or XS implementation.

sub self_updating { local $^W; *self_updating = sub{1} ;1 }
eval { $v = [1,2]->reduce(\&self_updating) };
is($@, '', 'redefine self');

{ my $failed = 0;

    sub rec { my $n = shift;
        if (!defined($n)) {  # No arg means we're being called by reduce()
            return 1; }
        if ($n<5) { rec($n+1); }
        else { $v = [1,2]->reduce(\&rec) }
        $failed = 1 if !defined $n;
    }

    rec(1);
    ok(!$failed, 'from active sub');
}