These are chat archives for rust-lang/rust

17th
Aug 2016
Te-jé Rodgers
@mr-rodgers
Aug 17 2016 14:14
This message was deleted
Zakarum
@omni-viral
Aug 17 2016 14:44
Incredible activity is in here
Richard Protasov
@rprotasov
Aug 17 2016 17:22

Hi there! I'm playing around with macros and I want to discern between 'simple' (e.g. one and four) and 'complex' (e.g. two:three) items.

For example, one/two:three/four should expand into something similar to

do_something(one);
do_something(two);
do_something(four);
do_something_else(two, three);

where there can a variable amount of items and complex items are in no particular location.

What I have some far is alike to

macro_rules! stuff {
    ( $($a:tt)/ * ) => ( $( stuff!(C $a); )* );
    ( C $n:ident ) => (/* */);
    ( C $n:ident : $m:ident ) => (/* */);
}

but I'm running into the issue where : (or any symbol-like separator) generates an error due to it being unexpected.

What would be a way to format a pattern to recognize the delimiters? Or am I going in the wrong direction with this?

To be honest what I have so far feels odd, but then again I'm not too familiar with macros 😅

Robert Deusser
@iamthemuffinman
Aug 17 2016 17:29
I find macros hard to write. They don't really make a lot of sense to me.
Erik Hedvall
@Ogeon
Aug 17 2016 17:30
The ordering of the patterns matters. I think it goes top to bottom and picks the first one it can find that seems to match.
Do you have a testable example of when it fails?
Richard Protasov
@rprotasov
Aug 17 2016 17:35
@iamthemuffinman true, my eyes glaze over staring at the bitwise cyclic tag example given in the book. @Ogeon sure, one moment.
Erik Hedvall
@Ogeon
Aug 17 2016 17:38
I played around a bit with what you have posted and one problem is the use of tt. It stands for token tree, as you probably know, and one/two:three/four isn't on the form tt / tt / tt / ..., but rather tt / tt tt tt / tt.
(don't bother with the example, I asked too soon)
Richard Protasov
@rprotasov
Aug 17 2016 17:43

Ahh, I see. Thanks for the clarification of that metavariable. Most places online describe it as a single token tree without a concrete example.

Well looking over the other fragments one doesn't seem to stand out to me that I can simply replace tt with.

Unless I'm missing something? lol
Erik Hedvall
@Ogeon
Aug 17 2016 17:47
That's right. They are quite simple on their own, but there are other techniques. A token tree is basically an identifier (a, foo, etc.) some punctuation or operator (., :, +, etc.) or other token trees, wrapped in some kind of delimiters (( ... ), [ ... ], etc.). There may be other subtleties, as well.
One popular technique is to match the beginning of the pattern and catch the rest in a $($rest:tt)*. The rest is then matched again, recursively, until you end up with nothing.
Erik Hedvall
@Ogeon
Aug 17 2016 17:53

It may look something like this in your case (untested):

macro_rules! stuff {
    ($n:ident / $($rest:tt)*) => (/* ... */ stuff!($($rest)*););
    ($n:ident : $m:ident / $($rest:tt)*) => (/* ... */ stuff!($($rest)*););
    () => (); //match the empty case
}

You can also pass more information if you has to keep a state around, which will be done in a similar way as what you have already.

Erik Hedvall
@Ogeon
Aug 17 2016 18:02
(The above example won't work, since it will complain about a missing / at the end)
Richard Protasov
@rprotasov
Aug 17 2016 18:03
Ahh interesting. Thanks so much for the explanations. I'm going to take another stab at it after a break, but I'm exponentially less confused now with what's up!
Erik Hedvall
@Ogeon
Aug 17 2016 18:16
Great! :smile: It'll probably fall into place after a little while. There was this really good site with many of these patterns and techniques, but I seem to have lost it. I'll post it if I happen to find it again.
Robert Deusser
@iamthemuffinman
Aug 17 2016 18:25
@Ogeon Thanks for the link!
nixfreak
@nixfreak
Aug 17 2016 21:43
is there a way to re-compile rust code on the fly but still have the program running? So add new code or new instructions to the program while its still running?
Peter Atashian
@retep998
Aug 17 2016 21:48
@nixfreak Not easily or nicely
and especially nothing that is actually supported
nixfreak
@nixfreak
Aug 17 2016 21:48
Would you have to have some kind of runtime env in the background ?
Robert Deusser
@iamthemuffinman
Aug 17 2016 22:12
I know Erlang (and assuming Elixir) can do this. It would be really cool if Rust could do this as well.
Not sure how it would work though.
Fletcher Haynes
@fhaynes
Aug 17 2016 22:23
Erlang/Elixir run on a virtual machine (BEAM)...Rust is compiled to native code. You'd need to write something similar for Rust, I imagine.
Alexander Ronald Altman
@pthariensflame
Aug 17 2016 22:49
There is libloading, of course.
Richard Protasov
@rprotasov
Aug 17 2016 23:01
@Ogeon nonce! I'll take a look through it sometime. Also they're working like a charm now 🤗