Public API and docs
This commit is contained in:
@@ -2,10 +2,12 @@ use std::cell::RefCell;
|
||||
use std::hash::Hash;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use trait_set::trait_set;
|
||||
|
||||
// TODO: make this a crate
|
||||
pub trait Callback<'a, I, O: 'static> = Fn(I, &Cache<'a, I, O>) -> O;
|
||||
|
||||
trait_set! {
|
||||
pub trait Callback<'a, I, O: 'static> = Fn(I, &Cache<'a, I, O>) -> O;
|
||||
}
|
||||
pub type CbBox<'a, I, O> = Box<dyn Callback<'a, I, O> + 'a>;
|
||||
|
||||
/// Cache the return values of an effectless closure in a hashmap
|
||||
|
||||
@@ -17,7 +17,6 @@ pub fn box_empty<'a, T: 'a>() -> BoxedIter<'a, T> {
|
||||
}
|
||||
|
||||
/// Chain various iterators into a [BoxedIter]
|
||||
#[macro_export]
|
||||
macro_rules! box_chain {
|
||||
($curr:expr) => {
|
||||
Box::new($curr) as BoxedIter<_>
|
||||
@@ -27,6 +26,8 @@ macro_rules! box_chain {
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use box_chain;
|
||||
|
||||
/// Flatten an iterator of iterators into a boxed iterator of the inner
|
||||
/// nested values
|
||||
pub fn box_flatten<
|
||||
@@ -40,7 +41,7 @@ pub fn box_flatten<
|
||||
Box::new(i.flatten())
|
||||
}
|
||||
|
||||
/// Convert an iterator into a Box<dyn Iterator>
|
||||
/// Convert an iterator into a `Box<dyn Iterator>`
|
||||
pub fn into_boxed_iter<'a, T: 'a + IntoIterator>(
|
||||
t: T,
|
||||
) -> BoxedIter<'a, <T as IntoIterator>::Item> {
|
||||
|
||||
@@ -6,7 +6,6 @@ mod side;
|
||||
mod string_from_charset;
|
||||
mod substack;
|
||||
mod unwrap_or;
|
||||
mod xloop;
|
||||
|
||||
pub use cache::Cache;
|
||||
pub use print_nname::sym2string;
|
||||
@@ -14,6 +13,7 @@ pub use pushed::pushed;
|
||||
pub use replace_first::replace_first;
|
||||
pub use side::Side;
|
||||
pub use substack::{Stackframe, Substack, SubstackIterator};
|
||||
pub(crate) use unwrap_or::unwrap_or;
|
||||
pub mod iter;
|
||||
pub use iter::BoxedIter;
|
||||
pub use string_from_charset::string_from_charset;
|
||||
|
||||
@@ -66,8 +66,8 @@ impl Side {
|
||||
Side::Right => (opposite, this),
|
||||
}
|
||||
}
|
||||
/// Produces an increasing sequence on Right, and a decreasing sequence
|
||||
/// on Left
|
||||
/// Walk a double ended iterator (assumed to be left-to-right) in this
|
||||
/// direction
|
||||
pub fn walk<'a, I: DoubleEndedIterator + 'a>(
|
||||
&self,
|
||||
iter: I,
|
||||
|
||||
@@ -56,6 +56,9 @@ impl<'a, T> Substack<'a, T> {
|
||||
Self::Bottom => 0,
|
||||
}
|
||||
}
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Debug> Debug for Substack<'a, T> {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/// A macro version of [Option::unwrap_or_else] which supports flow
|
||||
/// control statements such as `return` and `break` in the "else" branch.
|
||||
#[macro_export]
|
||||
macro_rules! unwrap_or {
|
||||
($m:expr; $fail:expr) => {{
|
||||
if let Some(res) = ($m) { res } else { $fail }
|
||||
}};
|
||||
}
|
||||
|
||||
pub(crate) use unwrap_or;
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/// Imitates a regular for loop with an exit clause using Rust's `loop`
|
||||
/// keyword. This macro brings the break value to all existing Rust loops,
|
||||
/// by allowing you to specify an exit expression in case the loop was
|
||||
/// broken by the condition and not an explicit `break`.
|
||||
///
|
||||
/// Since the exit expression can also be a block, this also allows you to
|
||||
/// execute other code when the condition fails. This can also be used to
|
||||
/// re-enter the loop with an explicit `continue` statement.
|
||||
///
|
||||
/// The macro also adds support for classic for loops familiar to everyone
|
||||
/// since C, except with the addition of an exit statement these too can
|
||||
/// be turned into expressions.
|
||||
///
|
||||
/// ```
|
||||
/// xloop!(for i in 0..10; {
|
||||
/// connection.try_connect()
|
||||
/// if connection.ready() {
|
||||
/// break Some(connection)
|
||||
/// }
|
||||
/// }; None)
|
||||
/// ```
|
||||
///
|
||||
/// While loop with reentry. This is a very convoluted example but
|
||||
/// displays the idea quite clearly.
|
||||
///
|
||||
/// ```
|
||||
/// xloop!(while socket.is_open(); {
|
||||
/// let (data, is_end) = socket.read();
|
||||
/// all_data.append(data)
|
||||
/// if is_end { break Ok(all_data) }
|
||||
/// }; {
|
||||
/// if let Ok(new_sock) = open_socket(socket.position()) {
|
||||
/// new_sock.set_position(socket.position());
|
||||
/// socket = new_sock;
|
||||
/// continue
|
||||
/// } else {
|
||||
/// Err(DownloadError::ConnectionLost)
|
||||
/// }
|
||||
/// })
|
||||
/// ```
|
||||
///
|
||||
/// CUDA algorythm for O(log n) summation using a C loop
|
||||
///
|
||||
/// ```
|
||||
/// xloop!(let mut leap = 1; own_id*2 + leap < batch_size; leap *= 2; {
|
||||
/// batch[own_id*2] += batch[own_id*2 + leap]
|
||||
/// })
|
||||
/// ```
|
||||
///
|
||||
/// The above loop isn't used as an expression, but an exit expression -
|
||||
/// or block - can be added to these as well just like the others. In all
|
||||
/// cases the exit expression is optional, its default value is `()`.
|
||||
///
|
||||
/// TODO: find a valid use case for While let for a demo
|
||||
/// TODO: break out into crate
|
||||
#[macro_export]
|
||||
macro_rules! xloop {
|
||||
(for $p:pat in $it:expr; $body:stmt) => {
|
||||
xloop!(for $p in $it; $body; ())
|
||||
};
|
||||
(for $p:pat in $iit:expr; $body:stmt; $exit:stmt) => {
|
||||
{
|
||||
let mut i = $iit.into_iter();
|
||||
xloop!(let Some($p) = i.next(); $body; $exit)
|
||||
}
|
||||
};
|
||||
(let $p:pat = $e:expr; $body:stmt) => {
|
||||
xloop!(let $p = $e; $body; ())
|
||||
};
|
||||
(let $p:pat = $e:expr; $body:stmt; $exit:stmt) => {
|
||||
{
|
||||
loop {
|
||||
if let $p = $e { $body }
|
||||
else { break { $exit } }
|
||||
}
|
||||
}
|
||||
};
|
||||
(while $cond:expr; $body:stmt) => {
|
||||
xloop!($cond; $body; ())
|
||||
};
|
||||
(while $cond:expr; $body:stmt; $exit:stmt) => {
|
||||
{
|
||||
loop {
|
||||
if $cond { $body }
|
||||
else { break { $exit } }
|
||||
}
|
||||
}
|
||||
};
|
||||
($init:stmt; $cond:expr; $step:stmt; $body:stmt) => {
|
||||
xloop!(for ( $init; $cond; $step ) $body; ())
|
||||
};
|
||||
($init:stmt; $cond:expr; $step:stmt; $body:stmt; $exit:stmt) => {
|
||||
{ $init; xloop!(while $cond; { $body; $step }; $exit) }
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user