标签: rust-macros

在 Rust 宏中将 ident 视为字符串

我有一个配置结构,其中包含一些顶级属性,我想将其放入各个部分中。我为了提供弃用警告,我制作了以下宏

macro_rules! deprecated {
($config:expr, $old:ident, $section:ident, $new:ident) => {
    if $config.$old.is_some() {
        println!(
            "$old configuration option is deprecated. Rename it to $new and put it under the section [$section]",
        );

        &$config.$old
    } else {
        if let Some(section) = &$config.$section {
            &section.$new
        } else {
            &None
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

}

这似乎没有按预期工作,因为宏参数没有在字符串中替换。如何改变宏才能达到想要的效果?

rust rust-macros

2
推荐指数
1
解决办法
2821
查看次数

如何匹配宏中的点并重建原始标记集?

我正在尝试编写一个宏来扩展它:

let res = log_request_response!(client.my_call("friend".to_string(), 5));
Run Code Online (Sandbox Code Playgroud)

进入这个:

let res = {
    debug!("Request: {}", args_separated_by_commas);
    let res = client.my_call("friend".to_string(), 5);
    debug!("Response: {}", res);
    res
};
Run Code Online (Sandbox Code Playgroud)

到目前为止我的尝试是这样的:

#[macro_export]
macro_rules! log_request_response_to_scuba {
    ($($client:ident)?.$call:ident($($arg:expr),*);) => {
        let mut s = String::new();
        $(
            {
                s.push_str(&format!("{:?}, ", $arg));
            }
        )*
        s.truncate(s.len() - 2);
        debug!("Request: {}", s);
        // Somehow reconstruct the entire thing with res = at the start.
        debug!("Response: {}", res);
        res
    };
}
Run Code Online (Sandbox Code Playgroud)

但这无法编译:

error: macro expansion ignores token `{` and any following
  --> src/main.rs:10:13 …
Run Code Online (Sandbox Code Playgroud)

rust rust-macros

2
推荐指数
1
解决办法
500
查看次数

解析 Rust 中的属性宏参数

我正在编写一个属性宏并尝试解析那里传递的参数。

喜欢:#[macro(Arg1, Arg2)]

问题是我找不到正确的结构来解析它。我尝试将其解析为MetaandMetaList但它们似乎都不起作用。

pub fn some_macro(args: TokenStream, item: TokenStream) -> TokenStream {
let args_parsed = parse_macro_input!(args as MetaList);

////////

let args_parsed = parse_macro_input!(args as Meta);

}
Run Code Online (Sandbox Code Playgroud)

当我解析它时,MetaList我得到:“意外的输入结束,预期的括号”错误。

rust rust-macros

2
推荐指数
1
解决办法
3726
查看次数

在宏中匹配下划线而不是ident

我正在创建一个匹配两个表达式和一个标识符的宏.如果不需要,我希望能够忽略标识符,但是如果我_在那里使用,编译器似乎会抱怨.

我的宏:

macro_rules! if_some {
    ($x:expr, $id:ident, $expr:expr) => {
        match $x {
            None => None,
            Some($id) => Some($expr),
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

我想做什么:

if_some!(obtain_an_option(), x, do_something_with(x))
Run Code Online (Sandbox Code Playgroud)

if_some!(obtain_an_option(), _, do_something())
Run Code Online (Sandbox Code Playgroud)

第二次通话失败.

我通过定义第二个if_some_!没有接收到标识符的宏来解决它(我也不能使用第二个模式).我确定有办法说"这里接受一个标识符或只是_.

也许已经有一个宏/功能(就像Option::map现在我想的那样)......不过现在它很好.

macros rust rust-macros

1
推荐指数
2
解决办法
201
查看次数

为什么基于抽象语法树的宏比基于字符串预处理的宏更好?

我开始学习Rust了.我通过示例Rust中遇到了这一行:

但是,与C和其他语言中的宏不同,Rust宏被扩展为抽象语法树,而不是字符串预处理,因此您不会遇到意外的优先级错误.

为什么抽象语法树比字符串预处理更好?

macros rust rust-macros

1
推荐指数
2
解决办法
174
查看次数

如何在 Rust 中创建匹配宏?

我正在尝试完成 Rustlings 练习中的测验 #4:

// 编写一个通过测验的宏!这次没有提示,你可以做到!

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_my_macro_world() {
        assert_eq!(my_macro!("world!"), "Hello world!");
    }

    #[test]
    fn test_my_macro_goodbye() {
        assert_eq!(my_macro!("goodbye!"), "Hello goodbye!");
    }
}
Run Code Online (Sandbox Code Playgroud)

我的宏看起来像这样:

#[macro_export]
macro_rules! my_macro {
    (($val:expr), "world!") => {
        println!("Hello world!");
    };
    (($val:expr), "goodbye!") => {
        println!("Hello goodbye!");
    };
}
Run Code Online (Sandbox Code Playgroud)

这是在 Rust 语言文档的声明性宏部分之后设计的。我收到以下错误:

assert_eq!(my_macro!("world!"), "Hello world!");
   |                              ^^^^^^^^^^ no rules expected this token in macro call

assert_eq!(my_macro!("goodbye!"), "Hello goodbye!");
   |                              ^^^^^^^^^^ no rules expected this token in macro call
Run Code Online (Sandbox Code Playgroud)

我找不到解决此问题的解决方案以使其编译。帮助!

rust rust-macros

1
推荐指数
1
解决办法
699
查看次数

为什么编译器不会自动在声明性宏中添加双括号?

在声明性宏中创建标识符时,必须在宏中添加额外的括号(双括号)。我想知道为什么编译器不只是(总是)添加额外的括号。

示例 1:此代码将无法编译,因为在必须使用双括号的情况下仅使用单括号:

macro_rules! some_macro {
    () => {
        let mut x = 1;

        x += 1;

        x
    };
}

fn main() {
    let y = some_macro!();
}
Run Code Online (Sandbox Code Playgroud)

添加双括号解决了编译错误。

示例 2:无论使用单括号还是双括号,此代码都会编译:

macro_rules! some_macro {
    () => {{
        1
    }};
}

fn main() {
    let y = some_macro!();
}
Run Code Online (Sandbox Code Playgroud)

是否存在带有双括号的宏破坏单括号宏的情况?如果没有,为什么编译器不总是添加双括号?

rust rust-macros

1
推荐指数
1
解决办法
62
查看次数

将嵌套结构字段路径作为宏参数传递

我是 Rust 的新手,我在编译以下代码时遇到了问题:

#![feature(trace_macros)]

fn main() {
    #[derive(Debug)]
    struct Inner {
      value: u8
    }
    
    #[derive(Debug)]
    struct Outer {
      inner: Inner
    }
    
    let mut x  = Outer { inner: Inner { value: 64 } };
    
    /********/
    
    macro_rules! my_macro {
        ($field_path:expr, $v:expr) => {
            x.$field_path = $v;
        }
    }

    trace_macros!(true);    
    // my_macro!(inner, Inner { value: 42 }); // only works with $field_path:ident
    my_macro!(inner.value, 42); // expected output: x.inner.value = 42;
    trace_macros!(false);
    
    x . inner.value = 42; // works fine
    
    assert_eq!(42, x.inner.value);
} …
Run Code Online (Sandbox Code Playgroud)

rust rust-macros

1
推荐指数
1
解决办法
201
查看次数

如何获取宏中变量的名称和值?

是否可以创建一个 Rust 宏来访问作为参数传递的变量的名称和值?

let my_variable: i32 = 5;
printvar!(my_variable); // => to print "my_variable = 5"
Run Code Online (Sandbox Code Playgroud)

例如,对于 C 宏,我们可以使用#运算符:

#include <stdio.h>

#define PRINT_VAR(x) printf("%s = %d\n", #x, x);

 int main() {
    int my_variable = 5;
    PRINT_VAR(my_variable);
}
Run Code Online (Sandbox Code Playgroud)
$ ./a.out
my_variable = 5
Run Code Online (Sandbox Code Playgroud)

macros rust rust-macros

1
推荐指数
1
解决办法
663
查看次数

是否可以通过使用该宏的结构内部的派生宏来更改/生成代码?

我很好奇是否可以更改使用派生宏的结构内部的代码,或者是否仅限于在外部生成新代码?

例子

通过 SomeMacro 将另一个字段添加到 Building 结构中。


#[derive(SomeMacro)]
pub struct Building {
  colour: String, 
  // Add height: u8 through derive macro
}
Run Code Online (Sandbox Code Playgroud)

rust rust-macros

1
推荐指数
1
解决办法
988
查看次数

是否可以为具有“key: value”语法的哈希图文字提供一个宏?

这个maplit板条箱允许哈希图文字作为=>分隔符。我相信不可能使用macro_rules!分隔:符,但是可以使用处理令牌流的宏吗?

是否不可能将{ key: value }样式宏添加到语言中,即使在编译器中也是如此?

我怀疑问题与:类型运算符冲突,但我无法构建一个不明确的示例,其中编译器无法决定以哪种方式解释:.

rust rust-macros

1
推荐指数
1
解决办法
1484
查看次数

如何在宏中调用self方法?

macro_rules! call_on_self {
    ($F:ident) => {
        self.$F()
    }
}

struct F;
impl F {
    fn dummy(&self) {}
    fn test(&self) {
        call_on_self!(dummy);
    }
}
Run Code Online (Sandbox Code Playgroud)

以上不起作用:

error[E0424]: expected value, found module `self`
  --> src/lib.rs:3:9
   |
3  |         self.$F()
   |         ^^^^ `self` value is a keyword only available in methods with `self` parameter
...
11 |         call_on_self!(dummy);
   |         --------------------- in this macro invocation
Run Code Online (Sandbox Code Playgroud)

我希望生成宏

macro_rules! call_on_self {
    ($F:ident) => {
        self.$F()
    }
}

struct F;
impl F {
    fn dummy(&self) {}
    fn test(&self) …
Run Code Online (Sandbox Code Playgroud)

rust rust-macros

0
推荐指数
1
解决办法
1490
查看次数

-2
推荐指数
2
解决办法
480
查看次数

标签 统计

rust ×13

rust-macros ×13

macros ×3

rust-cargo ×1