-
-
Notifications
You must be signed in to change notification settings - Fork 373
/
Set.pm
108 lines (92 loc) · 3.77 KB
/
Set.pm
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
106
107
108
my class Set is Iterable does Associative {
has %!elems;
method keys { %!elems.keys }
method values { %!elems.values }
method elems returns Int { %!elems.elems }
method exists($a) returns Bool { %!elems.exists($a) }
method Bool { %!elems.Bool }
method Numeric { %!elems.Numeric }
method hash { %!elems.hash }
method at_key($k) { ?(%!elems{$k} // False) }
method exists_key($k) { self.exists($k) }
# Constructor
method new(*@args --> Set) {
my %e;
sub register-arg($arg) {
given $arg {
when Pair { %e{.key} = True; }
when Set | KeySet { for .keys -> $key { %e{$key} = True; } }
when Associative { for .pairs -> $p { register-arg($p); } }
when Positional { for .list -> $p { register-arg($p); } }
default { %e{$_} = True; }
}
}
for @args {
register-arg($_);
}
self.bless(*, :elems(%e));
}
submethod BUILD (:%!elems) { }
# Coercions to and from
method postcircumfix:<( )> ($s --> Set) { to-set($s) }
multi to-set (Set $set --> Set) { $set }
multi to-set (KeySet $set --> Set) { Set.new: $set }
multi to-set (Bag $bag --> Set) { Set.new: $bag }
multi to-set (KeyBag $bag --> Set) { Set.new: $bag }
multi to-set (@elems --> Set) { Set.new: @elems }
multi to-set ([*@elems] --> Set) { Set.new: @elems }
multi to-set (%elems --> Set) { Set.new: %elems.keys }
multi to-set ($thing) { X::Set::Coerce.new(:$thing).throw }
multi method Str(Any:D $ : --> Str) { ~%!elems.keys() }
multi method gist(Any:D $ : --> Str) { "set({ %!elems.keys».gist.join(', ') })" }
multi method perl(Any:D $ : --> Str) { 'set(' ~ join(', ', map { .perl }, %!elems.keys) ~ ')' }
method iterator() { %!elems.keys.iterator }
method list() { %!elems.keys }
method pick($count = 1) { %!elems.keys.pick($count) }
method roll($count = 1) { %!elems.keys.roll($count) }
# TODO: WHICH will require the capability for >1 pointer in ObjAt
}
sub set(*@args) {
Set.new(@args);
}
my class KeySet is Iterable does Associative {
has %!elems;
method keys { %!elems.keys }
method values { %!elems.values }
method elems returns Int { %!elems.elems }
method exists($a) returns Bool { %!elems.exists($a) && %!elems{$a} }
method Bool { %!elems.Bool }
method Numeric { %!elems.Numeric }
method hash { %!elems.hash }
method at_key($k) {
Proxy.new(FETCH => { %!elems.exists($k) ?? True !! False },
STORE => -> $, $value { if $value { %!elems{$k} = True } else { %!elems.delete($k) }});
}
method exists_key($k) { self.exists($k) }
method delete_key($k) { %!elems.delete($k) }
# Constructor
method new(*@args --> KeySet) {
my %e;
sub register-arg($arg) {
given $arg {
when Pair { %e{.key} = True; }
when Set | KeySet { for .keys -> $key { %e{$key} = True; } }
when Associative { for .pairs -> $p { register-arg($p); } }
when Positional { for .list -> $p { register-arg($p); } }
default { %e{$_} = True; }
}
}
for @args {
register-arg($_);
}
self.bless(*, :elems(%e));
}
submethod BUILD (:%!elems) { }
multi method Str(Any:D $ : --> Str) { ~%!elems.keys }
multi method gist(Any:D $ : --> Str) { "keyset({ %!elems.keys».gist.join(', ') })" }
multi method perl(Any:D $ : --> Str) { 'KeySet.new(' ~ join(', ', map { .perl }, %!elems.keys) ~ ')' }
method iterator() { %!elems.keys.iterator }
method list() { %!elems.keys }
method pick($count = 1) { %!elems.keys.pick($count) }
method roll($count = 1) { %!elems.keys.roll($count) }
}