#why is this macros matcher giving me ambiguity error?

38 messages · Page 1 of 1 (latest)

gentle lion
#
macro_rules! print_log {
    ($type:expr, $( $($label:expr =>)? $arg:expr ),*) => { ... }
}

If I use it like print_log!("foo", evt => "added"), I get error on the evt: error: local ambiguity when calling macro print_log: multiple parsing options: built-in NTs expr ('label') or expr ('arg').

But the label token is supposed to be followed by a => so there shouldn't be any ambiguity here?

#

the macro works if I don't make the label optional:

#

($type:expr, $( $label:expr => $arg:expr ),*)

#

so I guess an alternative way to formulate the question is how do I make the $label token optional in this matcher?

untold swan
#

it needs to be able to decide which path to go before it can see the =>

gentle lion
#

oh wow that's fairly limiting

#

is it because that would make them way slower?

untold swan
#

somewhat there are other factors also

#

If you need a more powerful parser you can use a full proc macro that can parse the token sequence given however it wants to

#

You could also introduce some type of unique symbol for the branch with the label

gentle lion
#

starting to thing the best way to pretty log is just to make a Log everytime on the fly and have an impl block that edits the Log based on its shape
would that be too costly, creating a Log object everytime? Any advice on not making that expensive as logging can happens in loops and such...

untold swan
gentle lion
# untold swan are you using a logging framework?

I am using SimpleLogger, but I'd like the log components to be styled based on which type they are or which label they have or the name in case they don't have a label
That's why I switched to a macro, in order to capture the name without having to specify "foo=foo" everytime

#

Maybe there's already a framework out there that does this kind of styling considerations?

untold swan
#

A simple thing is to just modify the syntax you are working with

#

?play ```rust
macro_rules! print_log {
($type:expr, $( $(@ $label:expr =>)? $arg:expr ),*) => { todo!() }
}

fn main() {
print_log!("foo", @evt => "added")
}

neon basinBOT
#
     Running `target/debug/playground`
thread 'main' panicked at 'not yet implemented', src/main.rs:6:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
gentle lion
#

oh

untold swan
#

With something like the @ it knows which one it is beforehand

gentle lion
#

yeah I like it

untold swan
gentle lion
#

or a text file

untold swan
gentle lion
#

looking at those docs

#
span!(target: "app_spans", Level::TRACE, "my span");
event!(target: "app_events", Level::INFO, "something has happened!");
#

but I thought you couldn't use : in macros?

#

like in place of => above

#

oh maybe they can because they don't have a general expression

#

just the word target

#
let user = "ferris";

span!(Level::TRACE, "login", user);
// is equivalent to:
span!(Level::TRACE, "login", user = user);

they have the good stuff 😄

gentle lion
#

@untold swan added tracing to my create and it's working great
One thing I found is they have ? and % modifiers in order to use Display or Debug implementations of the types, since these are mostly implemented by the crates these types are defined in, and I want to define my own "Debug" implementation, is there anything similar but for custom representation?

#

Otherwise I'd have to wrap these in a newtype and implement debug on that

#

but if I do that inside the event! macro, the whole thing grows too big and I'd rather refactor that into a function, however I won't need that if there's a way to use a different format, might be overthinking this

eternal sage
#

?eval

macro_rules! example {
    ($type:expr, $( $($expr:expr)=>+  ),*) => {
        $(example_inner!{$type, $($expr)=>+})*
    }
}

macro_rules! example_inner {
    ($type:expr, $label:expr => $arg:expr ) => {
        println!("{}: {} => {}", $type, $label, $arg)
    };
    ($type:expr, $arg:expr ) => {
        println!("{}: {}", $type, $arg)
    };
}

fn main(){
    example!{"u32", 3 => 5}
    example!{"u64", 8}
    example!{"String", 13, 21 => 34}
}
neon basinBOT
#
     Running `target/debug/playground`

u32: 3 => 5
u64: 8
String: 13
String: 21 => 34