Построить вектор типов и инициализировать их - PullRequest
1 голос
/ 21 октября 2019

Я пытаюсь получить какой-то список типов, которые я могу затем инициализировать и построить генетические алгоритмы.

Проблема связана с самими "типами", я не нашел правильный способ принятьмассив типов и вызовите ::new для каждого, чтобы получить «экземпляр».

// --- conditions.rs ----------------------------------
extern crate strum;
use strum_macros::{EnumIter}; // etc.

pub trait Testable {
    fn new() -> Self;
    fn test(&self, candle: &Candle) -> bool;
}

// use strum::IntoEnumIterator;
#[derive(EnumIter,Debug)]
pub enum Conditions {
    SmaCheck,
    CandlesPassed,
}

// simple moving average check
pub struct SmaCheck {
    sma1: i8,
    sma2: i8,
}

impl Testable for SmaCheck {
    fn new() -> Self {
        Self { sma1: 10, sma2: 20 }
    }
    fn test(&self, candle: &Candle) -> bool {
        return true;
    }
}


// --- generator.rs -----------------------------------
// creates random conditions, which will then be mutated and bred

use strum::IntoEnumIterator;
use crate::conditions::{Conditions, Testable};


pub fn run() {
    for condition in Conditions::iter() {
        println!("{:?}", condition); // this works

        let testable = condition::new(); // undeclared type or module `condition`
        println!("{:?}", testable::new());
    }
}

1 Ответ

1 голос
/ 21 октября 2019

Кажется, что у вас есть перечисление, представляющее типы, и структура с тем же именем, что и у варианта перечисления.

Обратите внимание, что имена вариантов перечисления не имеют ничего общего с любыми типами, которые они могут представлять.

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

Однако ономожно взять перечисление неизвестного значения (средство проверки типов не может ограничить значения перечисления в любом случае) и вернуть значение на основе этого перечисления.

Кроме того, хотя метод может не возвращать неизвестные типы напрямую, вы можетеиспользуйте Box<dyn Trait>, чтобы обернуть значение неизвестного типа, или создайте перечисление, которое реализует черту и делегирует к запечатанным реализациям.

Следующее может быть ближе к тому, что вы хотели:

pub enum ConditionTypes {
    SmaCheck,
    CandlesPassed,
}

pub enum Condition {
    SmaCheck(SmaCheck), // the first word is the enum variant, the second word is the type of the value it contains
    CandlesPassed(CandlesPassed),
}

impl ConditionType {
    pub fn new(&self) -> Condition {
        match self {
            Self::SmaCheck => Condition::SmaCheck(SmaCheck::new()),
            Self::CandlesPassed => Condition::CandlesPassed(CandlesPassed::new()),
        }
    }
}

pub trait Testable {
    // we don't really need new() in this trait, do we?
    // if you want to use this trait when it could be of runtime-unknown type
    // instead of compile-time generics, all methods must have a receiver.

    fn test(&self, candle: &Candle) -> bool;
}

impl Testable for Condition {
    fn test(&self, candle: &Candle) -> bool {
        match self {
            Condition::SmaCheck(inner) => inner.test(candle),
            Condition::CandlesPassed(inner) => inner.test(candle),
        }
    }
}

// impl Testable for SmaCheck and CandlesPassed omitted

Это выглядит немного шаблонно, но есть макросы для получения этого.

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