Is it possible to generate a symbol or identifier in a Rust macro from a string? Or to perform string-like operations on a identifier?
I wanted to generate a method given a symbol, but need to downcase it to obtain the method name.
get!(B);
// should expand to
fn b() -> B {
// method body
}
It's easy to get close...
macro_rules! get {
($kind:ident, $method:ident)
=>
{
fn $method() -> $kind {
// method body
}
}
}
get!(B, b)
But dissatisfying.
I just wrote a procedural macro (casey) to do this.
#![feature(proc_macro_hygiene)]
use casey::lower;
lower!(B); // would render as `b`
proc_macro_hygiene
is stable as of rust 1.45.0, so no longer requires nightly.
The previous answers are all correct; standard declarative macros can't do this, and you can drop to procedural macros instead. However, a simpler alternative to procedural macros (especially if, like myself, that's an area of the language you haven't delved into yet) is dtolnay's paste crate.
An example from those docs:
use paste::paste;
paste! {
// Defines a const called `QRST`.
const [<Q R S T>]: &str = "success!";
}
fn main() {
assert_eq!(
paste! { [<Q R S T>].len() },
8,
);
}
Case conversion is also supported, e.g. [<ld_ $reg:lower _expr>]
No, there isn't a macro that can perform this sort of string manipulation on identifiers.
It is possible to create such a macro in the compiler, but it doesn't seem to be a popular need; today only the experimental concat_idents!
comes anything close to this (i.e. string-like operations for identifiers).
Your workaround is currently the only available solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With