It is impossible to do this in Rust or there are some trick such as RefCell or unsafe to circumvent it?
&mut _ are exclusive references, and it's UB to have an active &mut _ and active &_ to the same memory. That's what you're trying to do in the snippet. There is no way around that in particular.
Calling some function like parse_sign that way is basically trying to do something akin to calling
struct Struct {
field: String,
}
impl Struct {
fn example(&mut self, part_of_self: &str) {
*self = Struct { field: String::new() }
// `part_of_self` is still usable here... and for all you know,
// outside of the function too.
}
}
where part_of_self points inside field.
Another option, instead of using an &mut Parser outpointer, is to return an Option<Parser>. That is, use
struct Parser(Option<dyn Fn(char, &mut i32) -> Option<Parser>>);
Then, if a Some(parser) is returned, assign it to parser.
(My initial advice didnât work because I didnât look closely enough to see that the parser outpointer wasnât written on some branches.)
Thank you guys. Your instant answers makes me believe that Rust is a very good language and is very promising because of the active forum/community.
I get familiar with several horrible parts of the language. I'll strive to avoid them in the production code. I keep trying these things just for learning. Hope it didn't disturb you so much.
&mut _are exclusive references, and it's UB to have an active&mut _and active&_to the same memory. That's what you're trying to do in the snippet. There is no way around that in particular.
According to this, I may write the code below in the future. It's may not be so rusty but it should work.
struct Parser {
parse: Fn(&str),
}
// param will be captured
fn CreateParser(param: Param) {
Parser {
parse: |text| {
for c in text {
process(c, param.someValue);
}
}
}
}
let parser = CreateParser(someParam);
parser.parse(text);
And for state machine, I'll always stick to function pointer.
By the way, I think Rust should embrace async/await completely. In JS/TS, almost everything is async. I suggest Rust do the same. The whole standard runtime/library/grammar should be asynced in the future.
Bravo Rust!
How would async runtimes be written then? tokio is not compiler magic, nor is async-std.
I don't think I have sufficient knowledge to answer it. I just know that if I could write code like this in Rust:
async get {
let (res0, res1) = await join([
fetch("https://www.google.com"),
fetch("https://www.facebook.com"),
]);
return Response.json(merge(res0, res1));
}
I would be obsessed and not hesitate to write everything in Rust.
You can already write code like that in Rust. Rust has async functions and blocks, and an await operator (although it is postfix in Rust). The join function corresponds to the futures::join! macro (and it is being moved into std). The functions for getting the webpages could come from a library like reqwest, although the actual code would need to handle errors.
Rust having this functionality is very different from everything being async though. Many programs don't need to be async, and those that do will need a runtime to drive the execution of async code.
Fair enough. I'll try it ASAP.
Rust having this functionality is very different from everything being async though. Many programs don't need to be async, and those that do will need a runtime to drive the execution of async code.
Understand. Then make it as async as possible. Time will prove it.
I've held off on commenting about this before because I didn't want to distract from the specifics of the question you're asking, but there's a simpler, more idiomatic and, direct mapping of state machines in rust, enums and match.
For example your parse function may instead (with some more idomatic rust error handling) look like this playground snip:
That could be written a bunch of different ways, clearly, the idea is more just that you can directly describe the state you want with the data that state needs, and match on that and input simultaneously (by matching on a tuple)
Yes, I know. But eventually, the enum will be turned/mapped to a function which does the real thing. So using function pointer directly would be more efficient (and less code). In the mean time, it would let me touch the advanced parts of Rust.
I know I'm a little bit paranoid to pursuit extremity here. But if I were not, why choose Rust?
Thanks anyway. Let me know if there is more efficient or abnormal way.
Assumptions about performance can be very misleading! In particular, pushing the current state into a type-erased heap allocated function closure give the optimizer a lot more work (though I'd expect most of these to get erased)
That said, it is a good idea to try out the edges of a language to get familiar with it. I'm more just saying in Rust trying to keep callbacks around can quickly get pretty messy, and they aren't a good match for how you would use them on other languages at all, and there are instead different idioms and patterns that are better fits.
Actually, more often the opposite is true. Inlining is a prerequisite for many optimizations, and having a call through a function pointer would mean no inlining can happen. The optimizer even has a step which removes uses of function pointers when the functions are statically known, precisely because they would otherwise block further optimization.
Sure. Accepted.