Соответствие будущим типам
Я пытаюсь работать с фьючерсами, чтобы искать асинхронно искать значение. Если это значение существует, я хочу его вернуть, а если его нет, я хочу его создать.
// 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 ответ
Ваша самая очевидная ошибка ;
в конце None
ветка. Точка с запятой всегда отбрасывает значение предыдущего выражения, а блок, заканчивающийся точкой с запятой, имеет тип ()
(при условии, что конец достижим).
После удаления ;
вы увидите, что типы все еще не совпадают. Some
ветка имеет тип FutureResult<&NetworkDetails>
, в то время как None
ветка теперь имеет тип impl Future<Item = NetworkCreateInfo>
, Я не уверен, что вы пытаетесь сделать здесь, так как даже база NetworkDetails
а также NetworkCreateInfo
типы несовместимы. Вам нужно выяснить, какой тип вы хотите и как получить тот же тип в обеих ветвях.
Редактировать обновленный вопрос: Хорошо, вы хотите получить String
из обеих веток. У вас есть два разных типа, которые оба реализуют Future<Item = String>
черта, и вам нужно, чтобы обе ветви были одного типа. Это как раз цель future::Either
, Просто заверните одну ветку в Either::A
а другой филиал в Either::B
,
После этого вы также найдете тривиальную проблему заимствования в первой ветви: вам нужно скопировать строку с net.id.clone()
,