【问题标题】:Converting Rust macro types into expressions将 Rust 宏类型转换为表达式
【发布时间】:2016-09-12 15:15:54
【问题描述】:

我想假设给定类型使用方法(例如default())实现了某些特征(例如Default)。我想调用该方法并将其值存储到局部变量中。以下是它的总体思路:

macro_rules! get_default {
    (  $x:ty = $alias:ident ) => {
        let $alias = $x::default();
    };
}

fn main() {
    // get_default!(i32 = z); 
    // println!("get_default! {:?} ", z);
    println!("i32 default {:?} ", i32::default());
}

Playground link.

当我尝试得到错误时:

error: expected expression, found `i32`
 --> <anon>:3:22
  |>
3 |>         let $alias = $x::default();
  |>                      ^^

我理解这是因为它需要一个表达式,但我只想将输入限制为类型。有没有办法将$xty 转换为expr,或者调用某个类型的方法(即使它可能丢失)。

【问题讨论】:

    标签: macros rust


    【解决方案1】:

    你快到了。您可以向编译器提示预期的默认类型,然后只需使用 universal function call syntax:

    macro_rules! get_default {
        (  $x:ty = $alias:ident ) => {
            let $alias = <$x as Default>::default();
        };
    }
    
    fn main() {
        get_default!(i32 = z); 
        println!("get_default! {:?} ", z);
        println!("i32 default {:?} ", i32::default());
    }
    

    (Playground link)

    关键位是这样的:

    let $alias = <$x as Default>::default();
    

    这会将$x 转换为Default 特征,然后根据需要调用default() 方法。

    当您不需要消除特征之间的歧义时,您也可以使用简写:

    let $alias = <$x>::default();
    

    (Playground link)

    UFCS 的更多一般用法

    使用如上所示的 UFCS,您可以消除实现相同方法的特征之间的歧义。这是 'angle-bracket form',如果 default() 方法在两个特征中实现,这很有用。

    在这种特定场景下,您还可以更具体地使用 UFCS,如下所示:

    let $alias: $x = Default::default();
    

    仅此一项就为 Rust 提供了足够的信息来推断正确的 impl

    (Playground link)

    【讨论】:

    • 可能想补充一点,direct 方法是&lt;$x as Default&gt;::default()。通常,您可以使用&lt;Type&gt; 来引用路径中不直接有效的类型作为路径(包括宏替换、[_]&amp;T)。
    • 是的,DK 解决方案实际上是我正在寻找的,因为我想要一个更通用的解决方案,而不仅仅是使用 Default
    • @DK 扩展了关于您建议的方法的部分。如果我遗漏了任何您认为重要的细节,请随时提出建议。
    • @Aurora0001:我正在寻找的答案是&lt;$x as Default&gt;,注意我说的是例如Default。如果 trait 不返回 Self,我不能使用 let $alias: $x = Default::default(); 我以 Default 为例,因为这是我想到的第一个 trait。
    • @DanielFath:更新了我的答案,使其更像您想要的,并修复了过期的游乐场链接。
    猜你喜欢
    • 2022-09-25
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多