Macro_rules: is it possible to retrieve the last ident in a $e:expr?

Hello, just about curiosity : recently I noticed that I often use this pattern, especially when moving variables into closures:

let tx = tx.clone();

So, what about adding a friendly macro rule:

macro_rules! let_clone {
    ($id:ident) => {
        let $id = $id.clone();
    };
}

let_clone!(tx);

But later in my code, I saw this:

let tx = self.tx.clone();

Ok, so let's add a special rule in the macro_rules:

macro_rules! let_clone {
    ($id:ident) => {
        let $id = $id.clone();
    };
    ($parent:ident . $id:ident) => {
        let $id = $parent.$id.clone();
    };
}

let_clone!(self.tx);

But then I'm wondering if it's possible to handle a more general case, something like this:

macro_rules! let_clone {
    ($($expr:expr),* $(,)?) => {
        $(
            let last_ident_in_expr!($expr) = $expr.clone();
        )*
    };
}

The problem is I don't know how to implement last_ident_in_expr!(); I guess it's feasible with a proc macro, but is it possible with a simple macro rule ?

EDIT:
I can't imagine an "objective" implementation of the macro rule let_clone!() explained above, but in the context of this question, here are some examples of the use-cases I'm thinking about:

// let_clone!(a.x.y.z.foo);
let foo = a.x.y.z.foo.clone();
// let_clone!(a.x.y.z.foo());
let foo = a.x.y.z.foo().clone();
// let_clone!(a.x[42].y.z.foo());
let foo = a.x[42].y.z.foo().clone();

It's not possible in general, since expression will not always end in the ident - it can be a function call, for example, or just a literal.

1 Like

Thank you for your response :slightly_smiling_face: : indeed, it wouldn't be possible to handle all cases. Actually the title of my question is quite a summary of the use cases I was thinking about; I added an edit where I give some concrete use cases

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.