Массив методов в Rust - PullRequest
       71

Массив методов в Rust

0 голосов
/ 11 октября 2019

Я пытаюсь написать запрос «router» в Rust: список выражений, связанных с функциями, вызываемыми при совпадении. Функции могут быть методами, поступающими из различных объектов, что, конечно, приводит к тому, что контролер заимствований начинает жаловаться. Вот пример того, что я хотел бы:

use std::collections::HashMap;

struct Foo(bool);

impl Foo {
    fn say(&self) {
        println!("I'm {}", self.0);
    }
    fn morph(&mut self) {
        self.0 = !self.0;
    }
}

fn main() {
    let mut foo = Foo(true);

    let mut routes: HashMap<String, Box<FnMut()>> = HashMap::new();
    routes.insert("foo/say".to_string(), Box::new(|| foo.say()));  //< First (immutable) borrow of foo
    routes.insert("foo/morph".to_string(), Box::new(|| foo.morph())); //< Second (mutable) borrow of foo
    routes.insert("bar".to_string(), Box::new(|| println!("hello"))); //< Compiler also says immutable foo is used here
}

Я понимаю, почему средство проверки заимствований не в восторге от этого, но Мне интересно, какой может быть идиоматический способ реализации этого вRust .

Примечание: любые общие замечания о лучшем способе получения списка / массива / hashmap или любой коллекции разнородных функций будут приветствоваться.

1 Ответ

2 голосов
/ 11 октября 2019

Решение довольно простое, правда. Поскольку вам понадобится структура, которая позволит вам получить изменяемый заем по требованию, вам понадобится RwLock. И поскольку я предполагаю, что вы строите HTTP-маршрутизатор, чтобы обойти требования времени жизни на Foo, вы захотите обернуть это RwLock в Arc, вот так:

use std::collections::HashMap;
use std::sync::{Arc, RwLock};

struct Foo(bool);

impl Foo {
    fn say(&self) {
        println!("I'm {}", self.0);
    }
    fn morph(&mut self) {
        self.0 = !self.0;
    }
}

fn main() {
    let mut foo = Arc::new(RwLock::new(Foo(true)));

    let mut routes: HashMap<String, Box<FnMut()>> = HashMap::new();
    routes.insert("foo/say".to_string(), Box::new(|| foo.read().unwrap().say()));  //< First (immutable) borrow of foo
    routes.insert("foo/morph".to_string(), Box::new(|| foo.write().unwrap().morph())); //< Second (mutable) borrow of foo
    routes.insert("bar".to_string(), Box::new(|| println!("hello"))); //< Compiler also says immutable foo is used here
}

Обратите внимание, что я злоупотребил тем, что все может просто заимствовать foo только для чтения для этого. Если вам когда-либо понадобится move вещи в замыканиях, Arc реализует Clone, поэтому вам определенно следует воспользоваться этим.

В остальном все в порядке - если у всех замыканий одинаковая подписьупаковывать их и хранить в любой коллекции - идиоматизм.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...