如何从特定模块创建所有修饰函数的向量?

问题描述 投票:1回答:1

我有一个文件main.rs和一个文件rule.rs。我想在rule.rs中定义函数以包含在Rules::rule向量中,而不必逐个推送它们。我更喜欢循环来推动它们。

卖弄.人生:

struct Rules {
    rule: Vec<fn(arg: &Arg) -> bool>,
}

impl Rules {
    fn validate_incomplete(self, arg: &Arg) -> bool {
        // iterate through all constraints and evaluate, if false return and stop
        for constraint in self.incomplete_rule_constraints.iter() {
            if !constraint(&arg) {
                return false;
            }
        }
        true
    }
}

入了.人生:

pub fn test_constraint1(arg: &Arg) -> bool {
    arg.last_element().total() < 29500
}

pub fn test_constraint2(arg: &Arg) -> bool {
    arg.last_element().total() < 35000
}

Rules::rule应该有test_constraint1test_constraint2

在Python中,我可以在你想要包含在@rule_decorator中的约束上面添加一个装饰器Vec,但是我没有看到Rust中的等价物。

在Python中,我可以使用dir(module)来查看所有可用的方法/属性。

Python变种:

class Rules:

    def __init__(self, name: str):
        self.name = name
        self.rule = []

        for member in dir(self):
            method = getattr(self, member)
            if "rule_decorator" in dir(method):
                self.rule.append(method)

    def validate_incomplete(self, arg: Arg):
        for constraint in self.incomplete_rule_constraints:
            if not constraint(arg):
                return False
        return True

使用rule.py文件:

@rule_decorator
def test_constraint1(arg: Arg):
    return arg.last_element().total() < 29500

@rule_decorator
def test_constraint1(arg: Arg):
    return arg.last_element().total() < 35000

所有带有rule_decorator的函数都会被添加到self.rule列表中,并通过validate_incomplete函数进行检查。

module rust decorator
1个回答
0
投票

Rust没有与Python相同的反射功能。特别是,您无法在运行时迭代模块的所有函数。至少你不能用内置工具做到这一点。可以编写所谓的过程宏,它允许您向函数添加自定义属性,例如#[rule_decorator] fn foo() { ... }。使用proc宏,您几乎可以做任何事情。

但是,使用proc宏来进行过度设计(在我看来)。在您的情况下,我只列出要包含在向量中的所有函数:

fn test_constraint1(arg: u32) -> bool {
    arg < 29_500
} 
fn test_constraint2(arg: u32) -> bool {
    arg < 35_000
}

fn main() {
    let rules = vec![test_constraint1 as fn(_) -> _, test_constraint2];

    // Or, if you already have a vector and need to add to it:
    let mut rules = Vec::new();
    rules.extend_from_slice(
        &[test_constraint1 as fn(_) -> _, test_constraint2]
    );
}

关于此代码的一些注意事项:

  • 我用&Arg取代了u32,因为它与问题没有任何关系。请在StackOverflow上的问题中省略不必要的细节。
  • 我在数字文字中使用_来提高可读性。
  • 奇怪的as fn(_) -> _演员是可悲的必要。你可以在this question上阅读更多相关信息。
© www.soinside.com 2019 - 2024. All rights reserved.