Can't process result of function call


#1

Hello!
I am a newbee.
I am trying to write loop future.
The code is

    let packet_sender = future::loop_fn(kbucket_c.next(), move |peer| {
        if peer == None {
            return Ok(future::Loop::Break(peer));
        }
        // here, peer is not None
        let peer = peer.unwrap();
        let mut server = server_obj_c_c.borrow_mut();
        server.send_ping_req(peer)
            .and_then(|()| Ok(future::Loop::Continue(kbucket_c.next())))
            .or_else(|_| Ok(future::Loop::Break(kbucket_c.next())))
    })
    .map(|_| ());
    
    handle.spawn(packet_sender);

function named send_ping_req() returns IoFuture<()> type.
when it compiles
the error msg is

130 | / server.send_ping_req(peer)
131 | | .and_then(|()| Ok(future::loop::Continue(kbucket_c.next())))
132 | | .or_else(|_| Ok(future::loop::Break(kbucket_c.next())))
| |_______________________________________________________________________^ expected enum std::result::Result, found struct futures::OrElse
|
= note: expected type std::result::Result<_, _>
found type `futures::OrElse<futures::AndThen<std::boxed::Box<futures::Future<Error=std::io::Error, Item=()> + std::marker::Send>,

thanks in advance!!!


#2

(Please format error messages in your posts as well)

The loop_fn closure needs to return the same type, whereas it doesn’t in the code: it returns a Result and an OrElse. You can try one of these options:

  1. Use https://docs.rs/futures/0.1.18/futures/future/enum.Either.html as the return type, with A and B being different (Future) types that resolve to Loop.
  2. Box the two different futures you have now, which will erase the type. The return type will be Box<Future<Item=Loop...>>

#3

To flesh this out a bit, here’re the two options with code similar to yours (just enough to illustrate the idea):

fn option1() {
    let _ = future::loop_fn(next(), move |peer| match peer {
        None => Either::A(Ok::<_, ()>(future::Loop::Break(peer)).into_future()),
        Some(_peer) => Either::B(
            send_ping_req()
                .map(|()| future::Loop::Continue(next()))
                .or_else(|_| Ok(future::Loop::Break(next()))),
        ),
    });
}

type LoopFuture = Box<Future<Item = future::Loop<Option<Peer>, Option<Peer>>, Error = ()>>;

fn option2() {
    let _ = future::loop_fn(next(), move |peer| -> LoopFuture {
        match peer {
            None => Box::new(Ok(future::Loop::Break(peer)).into_future()),
            Some(_peer) => Box::new(
                send_ping_req()
                    .map(|()| future::Loop::Continue(next()))
                    .or_else(|_| Ok(future::Loop::Break(next()))),
            ),
        }
    });
}

#4

Thanks for your kind explanations!
I got it.