#'unwrap' enum to inner type?

18 messages · Page 1 of 1 (latest)

red wedge
#

Is there any other way to to implement anystate ? I'd like to have something like unwrap for when the yield and return type are the same.

#![feature(generators, generator_trait)]

extern crate core;

use core::{
    ops::{Generator, GeneratorState},
    pin::pin,
};

fn gen_fn() -> impl Generator<Yield = usize, Return = usize> {
    static || {
        let foo = "foo";
        let foo_ref = &foo;
        yield 0;
        yield foo_ref.len();
        return foo.len();
    }
}

pub fn add3(a:usize, b:usize, c:usize) -> usize {
    a + b + c
}

pub fn anystate<T>(gen: GeneratorState<T,T>) -> T {
    match gen {
        GeneratorState::Yielded(y) => y,
        GeneratorState::Complete(r) => r,
    }
}

pub fn bar() -> usize {
    let mut gen = pin!(gen_fn());
    let a = anystate(gen.as_mut().resume(()));
    let b = anystate(gen.as_mut().resume(()));
    let c = anystate(gen.as_mut().resume(()));
    add3(a,b,c)
}

pub fn main() {
    bar();
}
compact rose
#

I don't think there's any major differences that I know of....you can share the match arm though:

fn anystate<T>(gen: GeneratorState<T,T>) -> T {
    match gen {
        GeneratorState::Yielded(y) | GeneratorState::Complete(y) => y,
    }
}
fallen fjord
#

Can even skip the match, if you wanted:

fn anystate<T>(gen: GeneratorState<T,T>) -> T {
    let (GeneratorState::Yielded(y) | GeneratorState::Complete(y)) = gen;
    y
}
red wedge
#

Is there anyway I can extend the GeneratorState enum and impl a function called unwrap ? Like a blanket impl if the types are the same?

compact rose
#

Sure you can do that :), the implementation would be the same but yeah you could call it as a method instead

fallen fjord
#

Or the unreadable-but-possible

pub fn anystate<T>((GeneratorState::Yielded(y) | GeneratorState::Complete(y)): GeneratorState<T,T>) -> T {
    y
}
red wedge
#

That's the issue

fallen fjord
red wedge
#

Oh I thought that only applied to traits

fallen fjord
#

Well you define your own trait, which because it's your own trait you can implement on anything, including GeneratorState.

fallen fjord
#

Also, I suggest not calling it unwrap. You probably should call it into_inner or something, since it works very differently from Result::unwrap.

red wedge
#

@compact rose @fallen fjord Thank you for the help, much appreciated!

fallen fjord
#

More reading about extension traits if you'd like more of a walkthrough: http://xion.io/post/code/rust-extension-traits.html

red wedge
red wedge
#

generator_ext.rs

use core::ops::GeneratorState;

use extension_traits::extension;

#[extension(pub trait GeneratorStateExt)]
impl<T> GeneratorState<T, T> {
    fn into_inner(self) -> T {
        match self {
            GeneratorState::Yielded(y) => y,
            GeneratorState::Complete(r) => r,
        }
    }
}
#

main.rs

#![feature(generators, generator_trait)]

use core::{ops::Generator, pin::pin};

mod generator_ext;
use generator_ext::GeneratorStateExt;

fn gen_fn() -> impl Generator<Yield = usize, Return = usize> {
    static || {
        let foo = "foo";
        let foo_ref = &foo;
        yield 0;
        yield foo_ref.len();
        foo.len()
    }
}

pub fn add3(a: usize, b: usize, c: usize) -> usize {
    a + b + c
}

pub fn bar() -> usize {
    let mut gen = pin!(gen_fn());
    let a = gen.as_mut().resume(()).into_inner();
    let b = gen.as_mut().resume(()).into_inner();
    let c = gen.as_mut().resume(()).into_inner();
    add3(a, b, c)
}

pub fn main() {
    bar();
}