Giter VIP home page Giter VIP logo

Comments (13)

tgross35 avatar tgross35 commented on August 30, 2024 2

Regarding syntax, I would prefer a space-separated form like ${concat(get_ $item _mut)}, rather than the current comma-separated ${concat(get_, $item, _mut)}. That just makes it easier to read imo, and matches paste.

from rust.

fmease avatar fmease commented on August 30, 2024 1

All language features have to go through the RFC process eventually. However, the implementation can be done before an RFC has been written by following T-lang's experimental feature process which requires a T-lang member to support — shepherd — the venture. Only “small” language (not compiler) “fixes” don't need to follow the RFC process, they just need a T-lang FCP.

from rust.

UserIsntAvailable avatar UserIsntAvailable commented on August 30, 2024 1

Sorry if this is the wrong place to discuss this, but should ${concat} provide its own case-conversion mechanism (just like paste! does), or should we instead provide a standalone ${case} metavar expr to handle this?

If we where to follow paste! syntax, then it would look like:

macro_rules! many_idents {
    ($a:ident, $c:ident) => {
        const ${concat($a:upper, B, $c:lower, D)}: i32 = 1;
    };
}

fn main() {
    many_idents!(a, C);
    assert_eq!(ABcD, 1);
}

Or with a future ${case} metavar expr:

macro_rules! many_idents {
    ($a:ident, $c:ident) => {
        const ${concat(${case($a, upper)}, B, ${case($c, lower)}, D)}: i32 = 1;
    };
}

fn main() {
    many_idents!(a, C);
    assert_eq!(ABcD, 1);
}

Which I think is way too verbose, but maybe I'm just too used to paste! simplicity. The advantage of ${case} over ${concat} would be that, currently, ${concat} requires 2 operands to be able to be used (this could technically be changed), so ${case} would allow:

use std::ops::Add;

pub struct Wrapper<T>(T);

macro_rules! impl_op {
    ($Op:ident => $Ty:ty) => {
        impl $Op<$Ty> for Wrapper<$Ty> {
            type Output = Self;

            // alternative syntax; `:` instead of `,`.
            fn ${case($Op:snake)}(self, rhs: $Ty) -> Self::Output {
                Self(self.0.${case($Op:snake)}(rhs))
            }
        }
    };
}

impl_op!(Add => u8);

With that said, maybe there is a world where both approaches are accepted, but I think there is probably less motivation to do that?

cc @c410-f3r @joshtriplett for opinions about this.

from rust.

UserIsntAvailable avatar UserIsntAvailable commented on August 30, 2024 1

The introduction of ${case} as a new metavariable expression that can be used with or without ${concat} looks worth pursuing and semantically correct but IFAICT, inputs currently only accept ad-hoc parameters. More specifically, ${concat} only accepts literal identifiers and variables.

// Same problem with multiples `${concat}`s

macro_rules! foo {
    ($a:ident, $b:ident, $c:ident) => {
        let ${concat(a, ${concat(b, c)})}: () = (); // ERROR !
    }
}

Perhaps the evaluation of nested metaravariables expressions will become a thing someday?

Oh I wasn't aware of that limitation. I imagine that something like that would be needed down the line. I don't much about the internals of the macro codebase, so I wouldn't know if this would be hard to implement.

As a side note, I wonder if something like ${concat($a, concat($b, $c)} would be able to be made non ambiguous; I would imagine this kind of analysis would be hard to pull off, since you can't no longer look for ${} to know that the next thing is a metavar expr identifier.

$ident:modifier

Looks feasible in regards to a possible implementation but semantically awkward IMO. I am not aware of something similar in the macro system.

If acceptable, then it should probably be restricted to a subset of operations.

macro_rules! foo {
    ($a:ident) => {
        // Is it OK?
        let $a:upper = ();
    }
}

Do note that if $ident:modifier is accepted as the final syntax, it would only work inside of ${concat} or ${case}, which would remove the ambiguity for let $a:upper = ();; identifiers can't use the : symbol, so let ${case($a:upper)} = (); is non ambiguous.

With that said, you made me realize that with this change some metavar exprs would have "special syntax" attached to them, which might not be the desired design, specially because most users would think about metavar exprs as functions rather than "fancier macros" (although accepting this change would contradict this).

Another option would be to allow a standalone syntax ${$ident:modifier} (without writing case), but I don't know if case-conversion is important enough to have its own syntax (I also don't know what other modifiers you could really add to these).

These are just my opinions. A theoretical stabilization of ${concat} with or without case modifiers is fine to me.

This is something that can go under "Future possibilities" on the final RFC. I don't particularly think that stabilization should be blocked on this, since we can always add it later. :)

from rust.

fmease avatar fmease commented on August 30, 2024

This still needs a T-lang shepherd, right?

from rust.

c410-f3r avatar c410-f3r commented on August 30, 2024

This still needs a T-lang shepherd, right?

Unfortunately I am not familiar or aware of this procedure.

from rust.

fmease avatar fmease commented on August 30, 2024

T-lang, this feature is seeking a shepherd, therefore I'm nominating this for you.

An implementation is already under way (#118958). This feature adds a new kind of macro metavariable expression (the latter (overarching) feature has been approved by the merged RFC 3086, see also its tracking issue and stabilization PR (proposed FCP, disposition: merge)). The feature represents a more potent alternative / potential successor to the unstable built-in macro concat_idents (the latter has stalled, blocked on design concerns, see its tracking issue).

Please consult the tracking issue description for more context.

from rust.

joshtriplett avatar joshtriplett commented on August 30, 2024

Happy to second this with my T-lang hat on.

@c410-f3r Good luck, and please reach out to #t-lang on Zulip if you have any questions. Feel free to @ me there if needed.

from rust.

c410-f3r avatar c410-f3r commented on August 30, 2024

Thank you @joshtriplett

from rust.

c410-f3r avatar c410-f3r commented on August 30, 2024

Well, I personally don't mind discussing potential designs in a tracking issue.

${case}

The introduction of ${case} as a new metavariable expression that can be used with or without ${concat} looks worth pursuing and semantically correct but IFAICT, inputs currently only accept ad-hoc parameters. More specifically, ${concat} only accepts literal identifiers and variables.

// Same problem with multiples `${concat}`s

macro_rules! foo {
    ($a:ident, $b:ident, $c:ident) => {
        let ${concat(a, ${concat(b, c)})}: () = (); // ERROR !
    }
}

Perhaps the evaluation of nested metaravariables expressions will become a thing someday?

$ident:modifier

Looks feasible in regards to a possible implementation but semantically awkward IMO. I am not aware of something similar in the macro system.

If acceptable, then it should probably be restricted to a subset of operations.

macro_rules! foo {
    ($a:ident) => {
        // Is it OK?
        let $a:upper = ();
    }
}

These are just my opinions. A theoretical stabilization of ${concat} with or without case modifiers is fine to me.

from rust.

crumblingstatue avatar crumblingstatue commented on August 30, 2024

Is it a known issue that this doesn't seem to work with identifiers repeating at a depth?

#![feature(macro_metavar_expr_concat)]

macro_rules! many_idents {
    ($a:ident, $c:ident) => {
        const ${concat($a, B, $c, D)}: i32 = 1;
    };
}

// Paste implementation included for reference
macro_rules! many_idents_paste {
    ($a:ident, $c:ident) => {
        paste::paste! {
            const [<$a B $c D>]: i32 = 2;
        }
    };
}

macro_rules! many_idents_multi_metavar {
    ($($a:ident, $c:ident;)*) => {
        $(
            const ${concat($a, B, $c, D)}: i32 = 3;
        )*
    };
}

// Paste implementation included for reference
macro_rules! many_idents_multi_paste {
    ($($a:ident, $c:ident;)*) => {
        $(
            paste::paste! {
                const [<$a B $c D>]: i32 = 3;
            }
        )*
    };
}

fn main() {
    many_idents!(A, C);
    assert_eq!(ABCD, 1);
    many_idents_paste!(F, G);
    assert_eq!(FBGD, 2);
    many_idents_multi_paste! {
        H, I;
        J, K;
        L, M;
    }
    assert_eq!(HBID, 3);
    assert_eq!(JBKD, 3);
    assert_eq!(LBMD, 3);
    many_idents_multi_metavar! {
        N, O;
        P, Q;
        R, S;
    }
}
error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth
  --> src/main.rs:19:10
   |
19 |           $(
   |  __________^
20 | |             const ${concat($a, B, $c, D)}: i32 = 3;
21 | |         )*
   | |_________^

The paste version works without errors.

I can go a bit further with ignore

macro_rules! many_idents_multi_metavar {
    ($($a:ident, $c:ident;)*) => {
        $(
            ${ignore($a)}
            ${ignore($c)}
            const ${concat($a, B, $c, D)}: i32 = 3;
        )*
    };
}

But then I get:

error: `${concat(..)}` currently only accepts identifiers or meta-variables as parameters
  --> src/main.rs:22:29
   |
22 |             const ${concat($a, B, $c, D)}: i32 = 3;
   |     

This seems like a major limitation.

from rust.

c410-f3r avatar c410-f3r commented on August 30, 2024

Looks like a bug to me. I will try to investigate it in the following weeks

from rust.

tgross35 avatar tgross35 commented on August 30, 2024

It would be nice if there was some way to allow turning ${concat(c, $litstr)} into c"some string" for constructing C string literals when a Rust string is provided. That is, a replacement for cstr!. But I can't think of a good syntax here.

#127542 adds support for literals, but the above would get turned into (invalid) identifier csome string.

from rust.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.