macro_rules! apply_methods {
    ($($args:tt)*) => { ... };
}
Expand description

Utility to apply methods to an object.

Normally you would chain method calls like this:

foo
    .bar()
    .qux(5)
    .corge("yes", "no")

But with apply_methods! you can instead do this:

apply_methods!(foo, {
    .bar()
    .qux(5)
    .corge("yes", "no")
})

In addition to looking nicer, it has another benefit, which is that it supports macros:

apply_methods!(foo, {
    .bar!()
    .qux!(5)
    .corge!("yes", "no")
})

If you didn’t use apply_methods! then you would have to write this instead, which is a lot less readable:

corge!(qux!(bar!(foo), 5), "yes", "no")

It also supports macro paths:

apply_methods!(foo, {
    .some_crate::bar!()
    .other_crate::qux!(5)
    .nested::sub_crate::corge!("yes", "no")
})

And it supports specifying the type for method calls:

apply_methods!(foo, {
    .bar::<String>()
    .qux::<i32, i32>(5)
    .corge::<Vec<CustomType>>("yes", "no")
})

Creating custom macros

When using macros inside of apply_methods!, the object is always passed as the first argument to the macro:

macro_rules! my_macro {
    ($this:ident, $first:expr, $second:expr) => {
        ...
    };
}

// This is the same as doing `my_macro!(foo, 5, 10)`
//
// That means `$this` is a reference to `foo`
apply_methods!(foo, {
    .my_macro!(5, 10)
})

The first argument is always an ident, regardless of what the object is.

If the macro doesn’t accept any arguments, then it must be written like this, with a trailing comma:

macro_rules! my_macro {
    ($this:ident,) => {
        ...
    };
}

In addition to foo!() macros, you can also use foo![] and foo! {} macros.

And the macro can have whatever syntax it wants, because it’s a macro:

apply_methods!(foo, {
    .my_macro!(5; 10 => 15)

    .my_macro![5; 10 => 15]

    .my_macro! {
        foo = 5,
        bar = 10,
    }
})

Using $crate

Rust has a limitation where you cannot use $crate inside of macros, which means this does not work:

apply_methods!(foo, {
    .$crate::my_macro!(5, 10)
})

Instead you can workaround that by doing this:

extern crate self as my_crate;

apply_methods!(foo, {
    .my_crate::my_macro!(5, 10)
})

Alternatively, if you are using the html! or svg! macros then you can use the apply method:

html!("div", {
    .apply(|dom| $crate::my_macro!(dom, 5, 10))
})