pub struct Lazy<T> {
f : Option<Box<dyn FnOnce() -> T>>,
val : Option<T>,
}
impl<T> Lazy<T> {
pub fn new<F : FnOnce() -> T + 'static>(f : F) -> Lazy<T> {
Lazy {
f : Some(Box::new(f)),
val : None,
}
}
pub fn force(&mut self) {
if self.f.is_some() {
let mut f = None;
std::mem::swap(&mut f, &mut self.f);
let f = f.unwrap();
let result = (f)();
self.val = Some(result);
}
}
pub fn into_inner(mut self) -> T {
self.force();
let Lazy { f : _ , val } = self;
val.unwrap()
}
pub fn as_ref(&mut self) -> &T {
self.force();
self.val.as_ref().unwrap()
}
}
impl<T> AsMut<T> for Lazy<T> {
fn as_mut(&mut self) -> &mut T {
self.force();
self.val.as_mut().unwrap()
}
}
impl<T> Default for Lazy<T>
where T : Default {
fn default() -> Self {
Lazy {
f : None,
val : Some(T::default())
}
}
}
pub struct Seq<T>(Vec<Lazy<T>>);
impl<T> Seq<T> {
pub fn new() -> Seq<T> {
Seq(Vec::new())
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn capacity(&self) -> usize {
self.0.capacity()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn with_capacity(capacity : usize) -> Seq<T> {
Seq(Vec::with_capacity(capacity))
}
pub fn push<F : FnOnce() -> T + 'static>(&mut self, value : F) {
self.0.push(Lazy::new(value))
}
pub fn pop(&mut self) -> Option<T> {
let lazy = self.0.pop();
lazy.map(|l| l.into_inner())
}
pub fn force_all(&mut self) {
for i in 0..self.0.len() {
self.0[i].force()
}
}
pub fn to_vec(self) -> Vec<T> {
let Seq(vec) = self;
vec
.into_iter()
.map(|x| x.into_inner())
.collect()
}
pub fn to_lazy_vec(self) -> Vec<Lazy<T>> {
let Seq(vec) = self;
vec
}
pub fn get(&mut self, index : usize) -> Option<&T> {
self.0.get_mut(index).map(|l| { l.force(); l.as_ref() })
}
pub fn get_mut(&mut self, index : usize) -> Option<&mut T> {
self.0.get_mut(index).map(|l| { l.force(); l.as_mut() })
}
}
impl<T> From<Vec<Box<dyn FnOnce() -> T>>> for Seq<T> {
fn from(vec : Vec<Box<dyn FnOnce() -> T>>) -> Self {
Seq(
vec
.into_iter()
.map(|b| Lazy { f : Some(b), val : None })
.collect()
)
}
}
impl<T> From<Vec<T>> for Seq<T> {
fn from(vec : Vec<T>) -> Self {
Seq(
vec
.into_iter()
.map(|v| Lazy { f : None, val : Some(v) })
.collect()
)
}
}
impl<T> Default for Seq<T> {
fn default() -> Self {
Self::new()
}
}
#[macro_export]
macro_rules! seq {
() => (
lazy_seq::Seq::new()
);
($elem:expr; $n:expr) => (
{
let mut seq = Seq::with_capacity($n);
for _ in 0..$n {
seq.push($elem);
}
seq
}
);
($($x:expr),+ $(,)?) => (
{
let mut seq = Seq::new();
$(seq.push($x);)*
seq
}
);
}
#[cfg(test)]
mod tests {
use std::rc::Rc;
use std::cell::RefCell;
use crate::{Lazy, Seq, seq};
#[test]
pub fn lazy_correct() {
let counter = Rc::new(RefCell::new(0));
let counter_new = counter.clone();
let mut lazy = Lazy::new(
move || {
*counter_new.borrow_mut() += 1;
5 + 5
});
let result = lazy.as_ref();
assert_eq!(10, *result);
}
#[test]
pub fn seq_correct() {
let counter = Rc::new(RefCell::new(0));
let counter_new = counter.clone();
let mut seq = seq![
|| { 0 }; 9
];
assert_eq!(9, seq.len());
seq.push(move || {
*counter_new.borrow_mut() += 1;
println!("{:?}", counter_new);
5 + 5
});
assert_eq!(10, seq.len());
assert_eq!(0, *counter.borrow());
let _ = seq.get(9).unwrap();
assert_eq!(1, *counter.borrow());
seq.force_all();
let result = seq.pop();
assert_eq!(9, seq.len());
assert_eq!(1, *counter.borrow());
assert_eq!(10, result.unwrap());
}
}