ฉันจะใส่ฟังก์ชั่น async ลงในแผนที่ใน Rust ได้อย่างไร


11

ฉันไม่สามารถจัดการกับฟังก์ชั่น async hyperเขียนเมื่อเราเตอร์สำหรับ

รหัสนี้:

use std::collections::HashMap;
use std::future::Future;

type BoxedResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
type CalcFn = Box<dyn Fn(i32, i32) -> dyn Future<Output = BoxedResult<i32>>>;

async fn add(a: i32, b: i32) -> BoxedResult<i32> {
    Ok(a + b)
}

async fn sub(a: i32, b: i32) -> BoxedResult<i32> {
    Ok(a - b)
}

fn main() {
    let mut map: HashMap<&str, CalcFn> = Default::default();
    map.insert("add", Box::new(add));
    map.insert("sub", Box::new(sub));

    println!("map size: {}", map.len());
}

สร้างข้อผิดพลาดคอมไพเลอร์ต่อไปนี้:

error[E0271]: type mismatch resolving `<fn(i32, i32) -> impl std::future::Future {add} as std::ops::FnOnce<(i32, i32)>>::Output == dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
  --> src/main.rs:17:23
   |
17 |     map.insert("add", Box::new(add));
   |                       ^^^^^^^^^^^^^ expected opaque type, found trait std::future::Future
   |
   = note: expected type `impl std::future::Future`
              found type `dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
   = note: required for the cast to the object type `dyn std::ops::Fn(i32, i32) -> dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`

error[E0271]: type mismatch resolving `<fn(i32, i32) -> impl std::future::Future {sub} as std::ops::FnOnce<(i32, i32)>>::Output == dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
  --> src/main.rs:18:23
   |
18 |     map.insert("sub", Box::new(sub));
   |                       ^^^^^^^^^^^^^ expected opaque type, found trait std::future::Future
   |
   = note: expected type `impl std::future::Future`
              found type `dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
   = note: required for the cast to the object type `dyn std::ops::Fn(i32, i32) -> dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`

ดูเหมือนว่ามีข้อขัดแย้งระหว่างimpl Futureและdyn Futureแต่ฉันไม่รู้ว่าจะจัดการกับมันอย่างไร

คำตอบ:


5

สิ่งนี้เกิดขึ้นเพราะimpl Futureเป็นรูปแบบที่เป็นเอกลักษณ์เฉพาะในขณะที่dyn Futureเป็นรูปแบบนามธรรม HashMapคาดว่าจะเป็นประเภทนามธรรมเนื่องจากสามารถเก็บอินสแตนซ์ของประเภทเดียวได้เท่านั้น

ถ้าเราสามารถกล่องชนิดกลับของฟังก์ชั่น async HashMapเราจะสามารถที่จะเพิ่มฟิวเจอร์สเหล่านี้ลงใน

ก่อนอื่นเราต้องเปลี่ยนประเภทของCalcFn:

type CalcFn = Box<dyn Fn(i32, i32) -> Pin<Box<dyn Future<Output = i32>>>>;

จากนั้นสิ่งนี้สามารถทำเคล็ดลับ:

let mut map: HashMap<&str, CalcFn> = Default::default();
map.insert("add", Box::new(|a, b| Box::pin(add(a, b))));
map.insert("sub", Box::new(|a, b| Box::pin(sub(a, b))));

println!("map size: {}", map.len());

//map.get("add").unwrap()(2, 3).await

นี้ตัวอย่างที่สมบูรณ์ แบบง่ายFuture's Itemชนิดใช้แทนi32 Resultโปรดตรวจสอบรหัสเต็มรูปแบบสำหรับกรณีของคุณ


ตัวอย่างเต็มรูปแบบกับผู้ปฏิบัติการ
Ömer Erden

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.