rhaiscript / rhai

Rhai - An embedded scripting language for Rust.
https://crates.io/crates/rhai
Apache License 2.0
3.79k stars 177 forks source link

Good use case for Rhai? #115

Closed davideps closed 4 years ago

davideps commented 4 years ago

I'm new to Rust and asked this question in Discord. The response was to embed Lua in my application. Does this use case fit Rhai? Would Rhai be faster than Lua?

I have a Rust struct AGENT with fields like "gender" and "age". I also have a struct WORD with a field called "constraints" that I want to parse at runtime to determine if a WORD can be applied to an AGENT. Can this be done in Rust alone? If not, could I call Rhai to evaluate word.constraints such as:

"agent.age < 10 && agent.gender == "male"

How would Rhai receive a particular AGENT's age and gender?

schungx commented 4 years ago

This would be a common use case for Rhai:

#[derive(Debug, Clone)]
struct AGENT {
    pub gender: String,
    pub age: i64
}

impl AGENT {
    pub fn get_gender(&mut self) -> String { self.gender.clone() }
    pub fn get_age(&mut self) -> i64 { self.age }
}

fn main() -> Result<(), EvalAltResult> {
    // This is your agent
    let my_agent= AGENT { gender: "male".into(), age: 42 };

    // Create the engine
    let mut engine = Engine::new();

    // Register your AGENT type
    engine.register_type_with_name::<AGENT>("AGENT");
    engine.register_get("gender", AGENT::get_gender);
    engine.register_get("age", AGENT::get_age);

    // Create your context, add the agent as a constant
    let mut scope = Scope::new();
    scope.push_constant("agent", my_agent);

    // Evaluate the expression
    let result: bool = engine.eval_expression_with_scope(&mut scope, r#"
                                   agent.age < 10 && agent.gender == "male"
    "#)?;

    assert_eq!(result, false);

    Ok(())
}
schungx commented 4 years ago

I'm not sure if Rhai would be faster than Lua though... probably yes because Rhai is pretty minimal.

The benefit of using Rhai is no need to include the Lua library because Rhai is self-contained.

If you want to try it out, pull directly from GitHub as the current version on crates.io does not have support for evaluating expressions (only full scripts).

davideps commented 4 years ago

Thank you for your prompt answer and for describing a complete use case!

schungx commented 4 years ago

Now, depending on your database for WORD's and how frequently you'd be evaluating each criteria, it may be more efficient to pre-compile each criteria.

If you keep all the WORD criteria in memory all the time, and these criteria are evaluated repeatedly for different AGENT's, then you can consider to first compile each expression to an AST and store them inside your WORD. When you want to evaluate the criteria later, you no longer need to do the parsing again. You can directly evaluate the AST.

On the other hand, if your WORD's and criteria are stored in a database and retrieved on each run, then this is not going to help you - you have to parse each and every time.