-
-
Notifications
You must be signed in to change notification settings - Fork 372
/
Sequence.pm6
80 lines (66 loc) · 2.66 KB
/
Sequence.pm6
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
# A Sequence represents anything that can lazily produce a sequence of values.
# There are various concrete implementations of Sequence, the most common
# being Seq, which represents a sequentially produced sequence.
#
# Sequences are born in a state where iterating them will consume the values.
# However, calling .cache will return a List that will lazily reify to the
# values in the Sequence. The List is memoized, so that subsequent calls to
# .cache will always return the same List (safe as List is immutable). More
# than one call to .iterator throws an exception (and calling .cache calls the
# .iterator method the first time also). The memoization can be avoided by
# asking very specifically for the Seq to be coerced to a List (using .List
# or .list), a Slip (.Slip) or an Array (.Array).
#
# The actual memoization functionality is factored out into a role,
# PositionalBindFailover, which is used by the binder to identify types that,
# on failure to bind to an @-sigilled thing, can have .cache called on them
# and get memoization semantics. This decouples this functionality from the
# Sequence role, so other user-defined types can get access to this
# functionality.
my role PositionalBindFailover {
has $!list;
method cache() {
nqp::if(
nqp::isconcrete($!list),
$!list,
($!list := List.from-iterator(self.iterator))
)
}
multi method list(::?CLASS:D:) {
self.cache
}
method iterator() { ... }
}
nqp::p6configposbindfailover(Positional, PositionalBindFailover); # Binder
Routine.'!configure_positional_bind_failover'(Positional, PositionalBindFailover); # Multi-dispatch
my role Sequence does PositionalBindFailover {
multi method Array(::?CLASS:D:) { Array.from-iterator(self.iterator) }
multi method List(::?CLASS:D:) { List.from-iterator(self.iterator) }
multi method Slip(::?CLASS:D:) { Slip.from-iterator(self.iterator) }
multi method Str(::?CLASS:D:) {
self.cache.Str
}
multi method Stringy(::?CLASS:D:) {
self.cache.Stringy
}
method Numeric(::?CLASS:D:) { self.cache.elems }
multi method AT-POS(::?CLASS:D: Int:D $idx) is raw {
self.cache.AT-POS($idx)
}
multi method AT-POS(::?CLASS:D: int $idx) is raw {
self.cache.AT-POS($idx)
}
multi method EXISTS-POS(::?CLASS:D: Int:D $idx) {
self.cache.EXISTS-POS($idx)
}
multi method EXISTS-POS(::?CLASS:D: int $idx) {
self.cache.EXISTS-POS($idx)
}
multi method eager(::?CLASS:D:) { List.from-iterator(self.iterator).eager }
method fmt(|c) {
self.cache.fmt(|c)
}
multi method gist(::?CLASS:D:) {
self.cache.gist
}
}