Bamboo Shoot 3 comes with some general utilities for use with its own types and other programming. This briefly documents it.
All functions and classes are in namespace pbsu
.
Functions are documented with a brief type signature that is similar to what is used in Haskell; but there is no strict syntax on the signature, and any representation that easily makes sense is used. Some basic rules are:
arg_type -> ret_type
denotes a function;- type names beginning in lower case letters, e.g.
a
are unspecified types, and we are temporarily giving it a name, saya
in this case; - type names beginning in upper case letters are concrete types, or
concepts --- e.g.
Tuple<a, b>
means astd::tuple
ofa
andb
,Iterator<a>
means any type satisfying theIterator
concept, buta
andb
are not specified; - square brackets
[a]
denote an "iterable" (which is something that can be looped over byfor (auto x : iterable)
) containing typea
; again,a
is not specified; - functions of multiple or variadic arguments are expressed like
(a, b) -> c
or(a...) -> b
; in the latter case, each type ina...
may be different.
(Possibly) lazy ranges, packing a pair of iterators.
A pack of two iterators. .begin()
and .end()
returns the begin and
end. Has .size()
, .empty()
, operator bool
(true if non-empty) and
operator[]
if supported by underlying iterator.
Usually you need not explicitly create such a struct; use the helper make_range
Overloads:
[a] -> [a]
: wraps any iterable (e.g. C array,std::vector
,std::map
, ...) into astruct range
.(Iterator<a>, Iterator<a>) -> [a]
: wrap a pair of iterators into astruct range
.
Being a function, it can deduce parameter types. E.g.:
int a[3];
std::vector<double> b;
make_range(a); // same as a
make_range(b); // same as b
make_range(a+1, a+3); // contains a[1], a[2]
((a -> b), OutputIterator<b>) -> OutputIterator<a>
Transform input value by given f
then write to given output_iter
.
(OutputIterator<a>...) -> OutputIterator<a>
Return an OutputIterator
that writes input value unchanged into all given
outputs...
.
(OutputIterator<a>...) -> OutputIterator<Tuple<a...>>
Return an OutputIterator
taking Tuple
s, that writes 1st value to 1st
iterator, 2nd value to 2nd iterator, ...
((a -> Bool), OutputIterator<a>) -> OutputIterator<a>
If given predicate
returns true, write value to given output_iter
.
Otherwise do nothing.
((a -> b), Iterator<a>) -> Iterator<b>
Map values from it
by given f
.
This is used for input.
((a -> Bool), Iterator<a>, Iterator<a>) -> Iterator<a>
If predicate
returns true, use this value. Otherwise skip over it.
To make a corresponding end iterator, use
make_filtering_iterator(predicate, end, end)
. Note that you usually do
not need to do this: there is filter
.
Random access iterator incremented/decremented of step length 1
.
Dereferences to the corresponding integer.
([a], OutputIterator<a>) -> OutputIterator<a>
Write values in range
to output_iter
. Return the final output_iter
at last, same as
std::copy
.
([a]...) -> [Tuple<a...>]
Combine multiple ranges into one range, containing tuples of values from each range. Each input range is consumed in parallel one-by-one.
Lazy.
((a -> b), [a]) -> [b]
Map range
by f
--- returned range contains values as returned by
f(value_in_range)
.
This is lazy and guarantees ordered execution for all values till the last
used one (if an iterator is incremented before it was ever dereferenced, it
will be dereferenced first to ensure application of f
). For a version
that skips execution on unused values, use map_skipping
; if f
returns
equivalent values for same input, there is also map_ephemeral
which does
not store the results of f
and returns a prvalue. Note that the
ephemeral one can be more restricted that you think --- if f
returns
containers, then usually two results are not equivalent, in that an
iterator to the first result and an iterator to the second result cannot be
used together.
Map range
by f
with index applied as f(value, index)
. This uses the
default version of map
and there is no other variants at present.
((a -> Bool), [a]) -> [a]
Filter range
to what predicate
returns true.
Lazy.
Left fold of range
using f
. Uses
std::accumulate
.
Overloads:
(((a, b) -> a), a, [b]) -> a
: uses giveninit
as initial value;(((a, b) -> a), [b]) -> a
: uses first value inrange
as initial value, throwsstd::out_of_range
ifrange
is empty.
(((a...) -> b), Tuple<a...>) -> b
Call f
with arguments from tuple
.
<Int...> (((a...) -> b), Tuple<superset_of_a...>) -> b
Call f
with arguments from tuple
specified by given index...
.
({a -> b ...}, Tuple<a...>) -> Tuple<b...>
Here {a -> b ...}
means that f may be an object with multiple overloaded
operator()
or templated operator()
that can be called with different
types and return possibly different types.
Call f
with each value in tuple
, collect the result into a tuple.
A constref_forward()
has an operator()
that takes any value by constant
reference, return it unchanged in constant reference.
(((a...) -> b), a...) -> b
Call f
with args...
in reverse order.
(y -> z, ..., b -> c, a -> b) -> (a -> z)
Right-to-left function composition: returned function calls rightmost function first, then apply its return value to second rightmost function, and so on. Return the return value of first function.
(a -> b, b -> c, ..., y -> z) -> (a -> z)
Left-to-right function composition, similar to compose
.
(((a...) -> b)) -> (Tuple<a...> -> b)
spread(f)(tuple)
is equivalent to spread_call(f, tuple)
. It is like
partially-applied spread_call
with only the function.
<Int...> (((a...) -> b)) -> (Tuple<superset_of_a...> -> b)
Similar to spread
but used pick_call
.
a -> ((a -> b) -> b)
call_with(value)(f)
is equivalent to f(value)
.
((a -> b)...) -> (a -> Tuple<b...>)
Returned function applies given value to each f...
, collect their results
into a tuple.
Convert a number to its signed/unsigned type of same size. If
defined(DEBUG) || !defined(NDEBUG)
, performs out-of-range checking and
throws std::out_of_range
if the result would be incorrect.
Performs Computation
at most once, when requested by operator*
. Has
computation
as its public data member. Can be default constructed, or
constructed from an instance of Computation
.