-
Notifications
You must be signed in to change notification settings - Fork 3
/
functional-classes
executable file
·95 lines (72 loc) · 2.44 KB
/
functional-classes
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
#!/usr/bin/env perl
# Copyright (c) 2019 Christian Jaeger, [email protected]
# This is free software. See the file COPYING.md that came bundled
# with this file.
use strict;
use warnings;
use warnings FATAL => 'uninitialized';
# find modules from functional-perl working directory (non-installed)
use Cwd 'abs_path';
our ($mydir, $myname);
BEGIN {
my $location = (-l $0) ? abs_path($0) : $0;
$location =~ /(.*?)([^\/]+?)_?\z/s or die "?";
($mydir, $myname) = ($1, $2);
}
use lib "$mydir/../lib";
use Test::Requires qw(Moo);
# Comparison of imperative and functional approaches to some data
# container:
package ImperativePerson {
use Moo;
has name => is => 'ro';
has todo_items => is => 'ro'; # the array itself is the mutable part
sub add_todo {
my ($self, $item) = @_;
push @{ $self->{todo_items} }, $item;
}
}
package FunctionalPerson {
use FP::List; # for `cons`, `cons_`
use FP::Struct ["name", "todo_items"];
sub add_todo {
my ($self, $item) = @_;
# The sub receives the old todo_items list, and returns a new
# list with $item prepended:
#$self->todo_items_update(sub { cons $item, $_[0] })
# Or use `cons_` which returns a function that prepends
# cons_'s argument to its own argument:
$self->todo_items_update(cons_ $item)
}
_END_
}
use Test::More;
sub testImperative {
my $p = ImperativePerson->new(name => "Chris", todo_items => []);
$p->add_todo("buy bread");
$p->add_todo("walk dog");
is_deeply $p->todo_items, ['buy bread', 'walk dog'];
}
use FP::Equal qw(is_equal); # using FP::Equal's `equal` but still
# reporting via Test::More
use FP::List; # for `list`
sub testFunctional {
my $p = FunctionalPerson->new_(name => "Chris", todo_items => list());
# or, using positional arguments:
#my $p = FunctionalPerson->new("Chris", list());
# Each add_todo call returns a new version of the object, any
# pointer to the old version still sees the original value:
my $p2 = $p->add_todo("buy bread");
my $p3 = $p2->add_todo("walk dog");
is_equal $p3->todo_items, list('walk dog', 'buy bread');
is_equal $p2->todo_items, list('buy bread');
}
if ($ENV{RUN_TESTS}) {
testImperative;
testFunctional;
done_testing;
} else {
require FunctionalPerl;
import FunctionalPerl ":repl";
repl();
}