-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatomic.pl
More file actions
executable file
·99 lines (78 loc) · 2.12 KB
/
atomic.pl
File metadata and controls
executable file
·99 lines (78 loc) · 2.12 KB
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
#!/usr/bin/env perl
package Atomic;
use v5.32;
use warnings;
use feature 'signatures';
no warnings 'experimental::signatures';
sub value ($class, $value) {
my $ref = [ $value ];
return bless sub { $ref }, $class;
}
sub map ($self, $f) {
return bless sub {
my $ref = $self->();
return [ $f->($ref->[0]) ];
}, ref $self;
}
sub map2 ($self, $other, $f) {
return bless sub {
my $a = $self->()[0];
my $b = $other->()[0];
return [$f->($a, $b)];
}, ref $self;
}
sub get ($self) {
my $ref = $self->();
return $ref->[0];
}
sub set ($self, $x) {
my $ref = $self->();
$ref->[0] = $x;
return;
}
package main;
use v5.32;
use warnings;
use feature 'signatures';
no warnings 'experimental::signatures';
use open ':std', ':encoding(UTF-8)';
use Data::Printer;
use Math::Complex qw(:pi);
use Test::More;
my $radius = Atomic->value(1);
my $area = $radius->map(sub ($r) { $r * $r * pi });
# radius of 1
cmp_ok($radius->get, '==', 1, "radius of 1");
cmp_ok($area->get, '==', pi, "area of pi");
# set radius to 2
$radius->set(2);
cmp_ok($radius->get, '==', 2, "radius of 2");
cmp_ok($area->get, '==', (4*pi), "area of 2");
# Does nothing ...
$area->set(10);
cmp_ok($radius->get, '==', 2, "still radius of 2");
cmp_ok($area->get, '==', (4*pi), "still area of 2");
# Build two Vector type
my $x1 = Atomic->value(1);
my $y1 = Atomic->value(1);
my $x2 = Atomic->value(3);
my $y2 = Atomic->value(3);
my $v1 = $x1->map2($y1, sub ($x,$y) { vector($x,$y) });
my $v2 = $x2->map2($y2, sub ($x,$y) { vector($x,$y) });
my $v3 = $v1->map2($v2, sub ($v1,$v2) { vector_add($v1,$v2) });
is_deeply($v1->get, [1,1], "vector 1");
is_deeply($v2->get, [3,3], "vector 2");
is_deeply($v3->get, [4,4], "vector 3");
$x1->set(0);
$y2->set(10);
is_deeply($v1->get, [0,1], "vector 1 after changing x1/y2");
is_deeply($v2->get, [3,10], "vector 2 after changing x1/y2");
is_deeply($v3->get, [3,11], "vector 3 after changing x1/y2");
done_testing();
# A Vector type
sub vector($x,$y) {
return [$x, $y];
}
sub vector_add($v1, $v2) {
return [$v1->[0] + $v2->[0], $v1->[1] + $v2->[1]];
}