简体   繁体   English

将Rust宏类型转换为表达式

[英]Converting Rust macro types into expressions

I'd like to assume a given type implements some trait (eg Default ) with a method (eg default() ). 我想假设一个给定的类型用一个方法(例如default() )实现一些特征(例如Default )。 I want to call that method and store its value into a local variable. 我想调用该方法并将其值存储到局部变量中。 Here is a general idea of it: 以下是它的一般概念:

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 . 游乐场链接

When I try that I get an error: 当我尝试时,我收到一个错误:

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

I understand it's because it expects an expression, but I want to limit input to types only. 我理解这是因为它需要一个表达式,但我想将输入限制为仅仅类型。 Is there a way to turn $x from ty to expr , or a way to call a method on a type (even if it's potentially missing). 有没有办法将$xtyexpr ,或者是一种在类型上调用方法的方法(即使它可能缺失)。

You were almost there. 你快到了。 You can hint the expected default type to the compiler and then just use the 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 ) 游乐场链接

The key bit is this: 关键是这个:

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

This casts $x to the Default trait and then invokes the default() method, as you needed. 这会将$x转换为Default trait,然后根据需要调用default()方法。

You can also use a shorthand when you don't need to disambiguate between traits: 当您不需要消除特征之间的歧义时,您也可以使用速记:

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

( Playground link ) 游乐场链接

More General Usage of UFCS 更多UFCS的一般用法

Using UFCS as shown above, you can disambiguate between traits that implement the same methods. 使用如上所示的UFCS,您可以消除实现相同方法的特征之间的歧义。 This is the ' angle-bracket form ' which is useful if the default() method is implemented in two traits. 这是' 角括号形式 ',如果default()方法在两个特征中实现,这将非常有用。

In this specific scenario, you can also use UFCS more specifically, like so: 在此特定方案中,您还可以更具体地使用UFCS,如下所示:

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

That alone provides enough information for Rust to infer the correct impl . 仅这一点就为Rust提供了足够的信息来推断出正确的impl

( Playground link ) 游乐场链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM