Open stevedonovan opened 6 years ago
Awesome! I like the idea of a find that doesn't have an arcane obscure syntax. Yep, you are the first person to actually have a crate using it published. Good job :D
@luciusmagn We're considering using Rhai for a game project (https://www.github.com/veloren/game/). The team has a few questions about the language first though. Where is best to ask them?
I'd say here, or you can write me an email at luk.hozda@gmail.com. I am currently out of home, so it may take a while for me to respond
Dne pá 6. 7. 2018 10:48 uživatel Joshua Barretto notifications@github.com napsal:
@luciusmagn https://github.com/luciusmagn We're considering using Rhai for a game project (https://www.github.com/veloren/game/). The team has a few questions about the language first though. Where is best to ask them?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jonathandturner/rhai/issues/69#issuecomment-402970746, or mute the thread https://github.com/notifications/unsubscribe-auth/AIAzh6bJeD2eB_VIbrajwJi6iVse0VwYks5uDyRugaJpZM4TK_Rr .
I consider using Rhai for a game too. But I'm in the planning process and far away from any code
Another option for scripting would be Mun, but this is also in an early state
@MarkuBu my $0.02 worth - use Rhai if you want tight integration with lots of functionalities written in Rust. If you want to basically write your game logic in a scripting language, probably Lua is much more suited for this purpose.
@schungx why? Because of the performance? I know that Lua is fast, even without the JIT
Yes. Rhai is an AST-walking interpreter. It is never going to break any speed records. So use it where the majority of your application's time is not spend in the script.
Ok, thanks.
I'm looking for a scripting language to add dynamic helper support for my template engine handlebars-rust. By far Rhai seems to be a good fit because of its inter-operatability with rust data. I will be writing poc code recently and seeking for help with you.
No prob!
FYI support for rhai script helper has been released in handlebars 3.1.0 with a feature flag script_helper
https://github.com/sunng87/handlebars-rust/blob/master/examples/script.rs
I'm trying to integrate Rhai into my game but for the life of me I can't figure out how to pass a Vec of a custom Rust type (already registered with the engine) and access the indices from it.
I can successfully pass it but when the script tries to access any index it crashes.
When you pass a Vec
into Rhai, it treats it as a custom type. You're responsible for registering an API for use with that API. In your case, you'd want to register an indexer.
engine
.register_type_with_name::<Vec<MyType>>("Vec<MyType>")
.register_indexer_get_set(
|v: &mut Vec<MyType>, i: INT| v[i],
|v: &mut Vec<MyType>, i: INT, value: MyType| v[i] = value)
.register_fn("len", |v: &mut Vec<MyType>| v.len() as INT)
.register_get("len", |v: &mut Vec<MyType>| v.len() as INT)
.register_fn("contains", |v: &mut Vec<MyType>, value: MyType| v.contains(&value))
.register_fn("is_empty", |v: &mut Vec<MyType>| v.is_empty())
.register_get("is_empty", |v: &mut Vec<MyType>| v.is_empty());
After a while it gets clumsy. You'd want to use a plugin module to define the API instead.
Alternatively, you can convert the Vec<T>
into a Rhai Array
and it'll work with Rhai just fine.
// assuming 'my_vec' is 'Vec<T>'
let array: Dynamic = my_vec.into();
The catch is that a Rhai Array
is dynamically typed, meaning that you cannot restrict it to hold only MyType
.
@schungx Thank you very much for your help this is what I needed!
I'm using Rhai as a DSL for my memory profiler.
We are using rhai in our new GraphQL router project: https://github.com/apollographql/router
The router has a "plugin" framework which allows customer to write plugins in rust which may inspect or modify the flow of data through the router. We have a rhai plugin, which exposes router functionality so that plugins can also be written in rhai. This is nice for our customers, since it's much simpler to write a rhai plugin than a rust plugin.
Support is deemed to be experimental at the moment, but our experience so far is good!
This is interesting. Is your payload mostly binary-encoded or text-encoded (like JSON)?
Are you manipulating low-level transport streams with Rhai or pre-filled data objects?
BTW, it is usually simpler for the user to provide an overloaded version of a function that takes a string (as function name) in addition to one that takes an FnPtr
. This way, the user can skip the Fn
creation step. The implementation is usually simply to have the string version construct an FnPtr
and then call the FnPtr
version.
let request_callback = Fn("process_request");
service.map_request(request_callback);
let response_callback = Fn("process_response");
service.map_response(response_callback);
// can also call like this
service.map_request("process_request");
service.map_response("process_response");
// and the FnPtr versions will support this
service.map_request(|req| { ... });
service.map_response(|resp| { ... });
This is similar to early JavaScript style.
It's text-encoded (JSON), so it's mainly about manipulating pre-filled data objects.
Your comment made me chuckle because I originally (before I found out about Fn()) was just calling functions by string representation. I can't make my mind up if that looks better or not, but I'll try it out in a few examples so people are aware it exists.
We are using closures in one of the examples in a soon to land PR...
Your comment made me chuckle because I originally (before I found out about Fn()) was just calling functions by string representation. I can't make my mind up if that looks better or not, but I'll try it out in a few examples so people are aware it exists.
Why not both? I find Rhai's function overloading to be very useful in this regard, almost like writing JavaScript.
But you have to physically overload the function with a version that takes &str
parameter in order for that to work, so it is essentially a duplicated API.
Another tip:
// Leverage constants propagation to make scripts run faster
const request_callback = Fn("process_request");
service.map_request(request_callback);
const response_callback = Fn("process_response");
service.map_response(response_callback);
We are using rhai in vSMTP, a mail transfer agent made with rust.
Instead of filtering emails with a standard configuration format (like json or toml) we use Rhai to make powerful rules for filtering, enabling you to execute behavior on specific email addresses, clients, ip addresses etc ...
We are constantly trying to optimize the "rule engine" (the part that handles rhai) because the server needs to be really fast. But with the help of the team & rhai's great docs we are getting there :)
We are constantly trying to optimize the "rule engine" (the part that handles rhai) because the server needs to be really fast. But with the help of the team & rhai's great docs we are getting there :)
Let us know if you have an issue with this. The trick with performance is to avoid cloning like the plague, and sometimes it is not obvious.
You can also join the Discord channel for discussions.
BTW, just another tip-up. In your docs, you can link to https://rhai.rs/book/ref for a "Language Reference" section that contains only the scripting language, not the Rust engine bits. It would be easier on your users.
I'm using Rhai in https://github.com/YaLTeR/bxt-rs to script the goal and constraints for a brute-force optimizer. At first it was Lua (luajit), but then I couldn't figure out how to make it cross-compile out of the box on all system configurations that I care about, and tried Rhai as a pure-Rust option. Seems to work great so far; on the small scripts that I'm using it doesn't seem any slower than luajit.
it doesn't seem any slower than luajit.
If you're not repeatedly running a script in a tight loop, then the JIT doesn't really show its power...
During the optimization process normally the rest of the code takes much longer than the goal checking script, so yeah.
One performance bottleneck that I did hit with both luajit and Rhai is passing large arrays to the script (I guess specifically converting to luajit's tables or Rhai's Dynamic type). The script accepts either a single struct with a few fields (player data for the last state) or an array with several hundred of those structs (player data for all states). Ideally I'd unconditionally pass all states but it's quite slow to convert. Not sure how to improve this in a way that doesn't require writing manual field access or serialization code.
An option is to wrap that data structure in an Rc<Vec<Rc<Item>>>
. Then it is shared access and in general very very fast.
But then you'll have to register the relevant API's to access elements in the array (e.g. indexers) and fields access for Item
. The array must hold Rc
-wrapped values because you don't want to be copying items whenever you access an array slot - an indexer cannot return a ref mut
to the parent data.
But for high performance work when you don't want to copy things, it is worth it.
Others found via Used by:
(Consider converting this issue to a Discussion, sticky it and link to it from docs.)
I am using RHAI in https://rpgfx.com/ RPG Studio
Just a tracking issue for projects.
Apparently I've got the first published crate that uses Rhai as a dependency:
https://github.com/stevedonovan/findr