В Rust я могу выставить массив функций из моего модуля? - PullRequest
1 голос
/ 13 октября 2019

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

fn validate(game: &Game, next_move: String) -> Result<(), MoveError>

Вместо того, чтобы иметь потребителей этих правил use каждый модуль правил, я хотел бы представить набор (array? Vec<>?) из этих проверяющих функций. Я предполагал, что это будет массив указателей на функции, что-то вроде:

mod rule1;
mod rule2;

type Validate = fn(&Game, String) -> Result<(), MoveError>;

const validations: [Validate] = &[
    rule1::validate,
    rule2::validate
];

, но Руст говорит:

error[E0277]: the size for values of type `[for<'r> fn(&'r Game, std::string::String) -> std::result::Result<(), MoveError>]` cannot be known at compilation time
 --> src/lib.rs:6:20
  |
6 | const validations: [Validate] = &[
  |                    ^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `[for<'r> fn(&'r Game, std::string::String) -> std::result::Result<(), MoveError>]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

Я прочитал связанную статью и не стал мудрее. Какой первый шаг в исправлении этой ошибки (или, возможно, в исправлении моего непонимания)

Ответы [ 2 ]

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

Ваша проблема не имеет ничего общего с функциями.

Вы можете воспроизвести ее следующим образом:

const validation: [u32] = &[ 42 ];

, что дает

error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
 --> src/lib.rs:1:19
  |
1 | const validation: [u32] = &[ 42 ];
  |                   ^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `[u32]`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

Проблема в том, что[T] не является Sized типом, независимо от того, что T. Это означает, что вы не можете использовать его в const.

Однако вы можете использовать ссылку:

const validation: &[u32] = &[ 42 ];

или размерный массив:

const validation: [u32; 1] = [ 42 ];

То же относится и кВаша первоначальная проблема:


const validations: &[Validate] = &[
//                 ^
    rule1::validate,
    rule2::validate
];
0 голосов
/ 13 октября 2019
struct Game;
struct MoveError;

mod rule1 {
    use super::*;
    pub(crate) fn validate(game: &Game, s: String) -> Result<(), MoveError> {
        unimplemented!()
    }
}

mod rule2 {
    use super::*;
    pub(crate) fn validate(game: &Game, s: String) -> Result<(), MoveError> {
        unimplemented!()
    }
}

const VALIDATIONS: &[fn(&Game, String) -> Result<(), MoveError>] = &[
    rule1::validate,
    rule2::validate,
];

// or...

use lazy_static::lazy_static;

lazy_static! {
    static ref VALIDATIONS_2: &[Box<dyn Fn(&Game, String) -> Result<(), MoveError>>] = &[
        Box::new(rule1::validate),
        Box::new(rule2::validate)
    ];    
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...