-
Notifications
You must be signed in to change notification settings - Fork 190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a way to add a new unary operator? #962
Comments
Not at the moment. It was deemed before that unary operators are rare and not justified the complexity... |
Maybe you can overload the negative operator on your own data types? Just overload the function |
Thats what I did. The DSL was meant to be like this: let s = "Test";
- "some string: " ++ s ++ " and some number: " ++ 1234; where The problem is, that the let s = "Test";
(- "some string: ") ++ s ++ " and some number: " ++ 1234; which completely breaks the order of operation that I want. So my only option was possibly breaking negative values, by lowering the precedence (if even possible, I never tried tbh), which is a no-go for me or by making the syntax of the DSL uglier by only using functions (e.g.: All of this I didn't really like, so I wanted to go with the better option of adding a new operator ( In the meantime I figured out that I can just add custom syntax: {
let messages = engine.clone_messages();
engine
.register_custom_syntax(
["~", "$expr$"],
true,
move |context: &mut rhai::EvalContext,
inputs: &[rhai::Expression]|
-> ScriptResult<Dynamic> {
for e in inputs {
let result = context.eval_expression_tree(&e)?;
let mut m = flatten_dynamic(result)?;
messages.borrow_mut().append(&mut m);
}
Ok(Dynamic::UNIT)
},
)
.unwrap();
} Which works fine, but feels like it should be possible with just operators alone. |
Yes a custom syntax would be useful for this purpose. However, beware that you seem to require the print symbol to start a new line? Custom syntax are expressions so they don't necessarily start new lines. This may not be what you want. |
BTW what is the purpose of introducing a DSL? Since you can easily use the standard array literal syntax to create an array. |
Okay, so I'm building a code generation framework (SSD) in order to simplify the act of writing your own code generation tools. The framework has a defined data description format, which gets parsed and then handed off to one of the generators. In order to provide a simple way to generate text, I built a DSL on top of rhai where instead of having to write I thought this made for a nice DSL to write your code generation code in. And later found out that, because Some time ago, I needed to format something again and thought, why not rip the whole rhai part out of the framework and put it into its own crate (https://github.com/hardliner66/script-format/). After I was done I wrote some simple tests and documentation and thought its time to bump it to 1.0. Right after the release I asked a few friends for review and one of them experimented around with it, hitting a few bugs, but also a few inconsistencies. The tool basically started printing things it shouldn't or get the order slightly wrong, because most operators I introduced had side effects. I also somehow never thought about using So in order to mitigate the issues, I removed all the implicit printing and opted for a slightly less nice, but more straight forward syntax where Which is where I hit the problem of So its not that I need a DSL for concatenating values, but concatenating values like this is just what remained of the original when removing the implicit printing. Handling it this way also ensures that no matter the order of operations, it will always get concatenated correctly before the whole result gets committed for printing.
Not necessarily. I just need it to be treated like a print call, that takes all the values to its right, which it currently does. Using it inside an expression would be the same as using print in the middle of an expression, which is why I don't mind that thats a possibility. If unary operators are a possibility in the future, I'll probably still switch to them, because I feel they are already close to what I need and I don't like to use the big guns, so to speak, unless necessary. Hope that clarifies the use-case a bit. |
That's very clear. One thing that threw me off is that you may be able to use Rhai's standard You just define - "some string: " + s + " and some number: " + 1234; You can even use strings interpolation which is essentially the same thing. - `some string: ${s} and some number: ${1234}` I wonder what functionality that your Just trying to understand your use case to see why it isn't adequately covered. |
When dealing with constructing strings dynamically I tend to push all parts in a vec first and then join it into the final string, because it's easier to deal with the individual parts. The ++ operator takes two elements and puts them into a vec. It also flattens the elements if necessary. It's probably possible to just use + instead, but as I said, the ++ operator used to not only concat, but also print, so having it be different from + was a good idea. And, from a backwards compatibility standpoint, I didn't want to change too much syntax at once. I even left the unary - in and just show a depreciation notice to make the transition easier. So in short: it might not be strictly necessary anymore to have a custom operator for that purpose, but there's historical reason for it and I also like the differentiation of ++ being to concat output strings versus + being for other coding. Edit: |
Thanks for your detailed replies. Very clear now. I'll look into adding custom unary operators. It may not be as straightforward as it sounds currently unary operators are always bound before binary ones are considered. So it may not be possible to change it to a low precedence. |
I have written a DSL to format objects with rhai and recently, when trying to fix some bugs, I found out that those bugs stem from me abusing the unary operator
-
for printing. The problem is that if I were (able) to fix this for the minus operator, it would break code that uses the minus operator in the intended way. So instead I tried to use a different symbol as a unary operator (with really low precedence), but the parser always returns an error, saying the symbol wasn't expected there.So, is there a way to add a new unary operator?
The text was updated successfully, but these errors were encountered: