如何从特定模块创建包含所有修饰函数的向量? [英] How to create a vector of all decorated functions from a specific module?

查看:71
本文介绍了如何从特定模块创建包含所有修饰函数的向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文件main.rs和一个文件rule.rs.我想在rule.rs中定义要包含在Rules::rule向量中的函数,而不必一一推送.我希望有一个循环来推动它们.

I have a file main.rs and a file rule.rs. I want to define functions in rule.rs to be included in the Rules::rule vector without having to push them one by one. I'd prefer a loop to push them.

main.rs :

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
    }
}

rule.rs :

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中,我可以在要包含在Vec中的约束之上添加装饰器@rule_decorator,但是在Rust中看不到装饰器.

In Python, I could add a decorator @rule_decorator above the constraints which you want to be included in the Vec, but I don't see an equivalent in Rust.

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

In Python, I could use dir(module) to see all available methods/attributes.

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文件:

With the rule.py file:

@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功能选中.

All functions with a rule_decorator are added to the self.rule list and checked off by the validate_incomplete function.

推荐答案

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

Rust does not have the same reflection features as Python. In particular, you cannot iterate through all functions of a module at runtime. At least you can't do that with builtin tools. It is possible to write so called procedural macros which let you add custom attributes to your functions, e.g. #[rule_decorator] fn foo() { ... }. With proc macros, you can do almost anything.

但是,为此,使用proc宏的方法过于工程化(我认为).就您而言,我只列出所有要包含在向量中的函数:

However, using proc macros for this is way too over-engineered (in my opinion). In your case, I would simply list all functions to be included in your vector:

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]
    );
}

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

A few notes about this code:

  • 我用u32替换了&Arg,因为它与问题无关.请忽略有关StackOverflow问题的不必要的详细信息.
  • 我在数字文字中使用了_以提高可读性.
  • 奇怪的as fn(_) -> _强制转换很可惜.您可以在这个问题.
  • I replaced &Arg with u32, because it doesn't have anything to do with the problem. Please omit unnecessary details from questions on StackOverflow.
  • I used _ in the number literals to increase readability.
  • The strange as fn(_) -> _ cast is sadly necessary. You can read more about it in this question.

这篇关于如何从特定模块创建包含所有修饰函数的向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆