Соответствие будущим типам - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь работать с фьючерсами, чтобы искать асинхронно, искать значение. Если это значение существует, я хочу его вернуть, а если его нет, я хочу его создать.

// A network will be created unless one already exists with this name
pub fn build_network(name: &'static str) {
    let docker = Docker::new();

    // Get a list of networks
    let fut = docker
        .networks()
        .list(&Default::default())
        .and_then(move |networks| {
            // Check if a network with the given name exists  
            let network = networks.iter().find(|n| n.name == name);

            match network {
                // Pass on network
                Some(net) => future::ok(net.id),
                // Create a new network
                None => {
                    let docker = Docker::new();
                    docker
                        .networks()
                        .create(&NetworkCreateOptions::builder(name).driver("bridge").build())
                        .map(|new_net| new_net.id)

                }
            }
        })
        .map(move |net| {
            println!("{:#?}", net);
        })
        .map_err(|e| eprintln!("Error: {}", e));

    tokio::run(fut);
}

Похоже, что в моем выражении соответствия есть несоответствие типов. Я пытаюсь убедиться, что каждая рука содержит будущее для структуры сети грузоподъемника, но похоже, что я не совсем понимаю.

error[E0308]: match arms have incompatible types
   --> src/up/mod.rs:168:13
    |
168 | /             match network {
169 | |                 // Pass on network
170 | |                 Some(net) => future::ok(net.id),
171 | |                 // Create a new network
...   |
178 | |                 }
179 | |             }
    | |_____________^ expected struct `futures::FutureResult`, found struct `futures::Map`
    |
    = note: expected type `futures::FutureResult<std::string::String, _>`
               found type `futures::Map<impl futures::Future, [closure@src/up/mod.rs:177:30: 177:50]>`
note: match arm with an incompatible type
   --> src/up/mod.rs:172:25
    |
172 |                   None => {
    |  _________________________^
173 | |                     let docker = Docker::new();
174 | |                     docker
175 | |                         .networks()
176 | |                         .create(&NetworkCreateOptions::builder(name).driver("bridge").build())
177 | |                         .map(|new_net| new_net.id)
178 | |                 }
    | |_________________^

error: aborting due to previous error

1 Ответ

0 голосов
/ 08 января 2019

Ваша самая очевидная ошибка - ; в конце ветви None. Точка с запятой всегда отбрасывает значение предыдущего выражения, а блок, заканчивающийся точкой с запятой, имеет тип () (при условии, что конец достижим).

После удаления ; вы увидите, что типы по-прежнему не совпадают. Ветвь Some имеет тип FutureResult<&NetworkDetails>, а ветвь None теперь имеет тип impl Future<Item = NetworkCreateInfo>. Я не уверен, что вы пытаетесь сделать здесь, поскольку даже базовые типы NetworkDetails и NetworkCreateInfo несовместимы. Вам нужно выяснить, какой тип вам нужен и как получить один и тот же тип в обеих ветвях.

Изменить для обновленного вопроса: Хорошо, вы хотите получить String из обеих веток. У вас есть два разных типа, которые реализуют черту Future<Item = String>, и вам нужно, чтобы обе ветви были одного типа. Это как раз цель future::Either. Просто оберните одну ветку в Either::A, а другую - в Either::B.

После этого вы также обнаружите тривиальную проблему заимствования в первой ветви: вам нужно скопировать строку с помощью net.id.clone().

...