Do you mean something like this:
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::thunk::Invoke;
enum LazyInner<'a, T> {
Uninitialized(Option<Box<Invoke<(), T> + 'a>>),
Initialized(T),
}
pub struct Lazy<'a, T> {
inner: UnsafeCell<LazyInner<'a, T>>,
}
impl<'a, T> Lazy<'a, T> {
pub fn new<F: 'a>(f: F) -> Self where F: FnOnce() -> T {
Lazy {
inner: UnsafeCell::new(LazyInner::Uninitialized(Some(Box::new(move |()|f()))))
}
}
}
impl<'a, T> Deref for Lazy<'a, T> {
type Target = T;
fn deref(&self) -> &T {
use LazyInner::*;
unsafe {
match *self.inner.get() {
Uninitialized(ref mut f) => match f.take() {
Some(f) => {
*self.inner.get() = Initialized(f.invoke(()));
&self
},
None => unreachable!(),
},
Initialized(ref value) => value,
}
}
}
}
impl<'a, T> DerefMut for Lazy<'a, T> {
fn deref_mut(&mut self) -> &mut T {
use LazyInner::*;
unsafe {
match *self.inner.get() {
Uninitialized(ref mut f) => match f.take() {
Some(f) => {
*self.inner.get() = Initialized(f.invoke(()));
&mut *self
},
None => unreachable!(),
},
Initialized(ref mut value) => value,
}
}
}
}
macro_rules! lazy {
($($s:stmt);+) => {{
Lazy::new(|| { $($s);+ })
}};
}
macro_rules! movable_lazy {
($($s:stmt);+) => {{
Lazy::new(move || { $($s);+ })
}};
}
fn test(value: &Lazy<u8>) {
println!("{}", **value);
}
fn main() {
let l = lazy! {
println!("computing");
1u8 + 2 + 3 + 4
};
test(&l);
test(&l);
}
I doubt this functionality will ever be included in rust itself because it’s a very high level concept and is not a zero-cost abstraction but those macros work fairly well (but could clearly be improved/optimized).