为了账号安全,请及时绑定邮箱和手机立即绑定

如何在RUST中打印变量的类型?

如何在RUST中打印变量的类型?

我有以下情况:let mut my_number = 32.90;如何打印my_number?使用type和type_of不起作用。还有别的方法可以打印号码的字体吗?
查看完整描述

4 回答

?
萧十郎

TA贡献1815条经验 获得超12个赞

如果你只是想找出变量的类型,并且愿意在编译时这样做,您可以导致一个错误并让编译器来获取它。

例如,将变量设置为无法工作的类型 (let () = x;):

error[E0308]: mismatched types
 --> <anon>:2:29
  |
2 |     let mut my_number: () = 32.90;
  |                             ^^^^^ expected (), found floating-point variable
  |
  = note: expected type `()`
  = note:    found type `{float}`

error: aborting due to previous error

或者在大多数情况下调用无效方法获取无效字段:

error: no method named `what_is_this` found for type `{float}` in the current scope
 --> <anon>:3:15
  |
3 |     my_number.what_is_this();
  |               ^^^^^^^^^^^^

error: aborting due to previous error
error: attempted access of field `what_is_this` on type `{float}`, but no field with that name was found
 --> <anon>:3:5
  |
3 |     my_number.what_is_this
  |     ^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

这些都揭示了类型,在这种情况下,这种类型实际上还没有完全解决。在第一个例子中,它被称为“浮点变量”,并且{float}“在所有三个示例中,这是一个部分解析的类型,可能会以f32f64,取决于你如何使用它。“{float}不是合法的类型名称,它是一个占位符,意思是“我不完全确定这是什么”,但它浮点数。在浮点变量的情况下,如果不对其进行约束,它将默认为f641,1。(非限定整数文字默认为i32.)


可能仍有一些方法使编译器感到困惑,使编译器无法在两者之间作出决定。f32f64我不确定。它过去很简单32.90.eq(&32.90),但这两者都被视为f64现在快乐地向前走,所以我不知道。


查看完整回答
反对 回复 2019-07-13
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

有一个不稳定的函数std::intrinsics::type_name这可以为您提供一个类型的名称,尽管您必须使用一个夜间构建的RUST(这不太可能在稳定锈蚀中起作用)。下面是一个例子:

#![feature(core_intrinsics)]fn print_type_of<T>(_: &T) {
    println!("{}", unsafe { std::intrinsics::type_name::<T>() });}fn main() {
    print_type_of(&32.90);          // prints "f64"
    print_type_of(&vec![1, 2, 4]);  // prints "std::vec::Vec<i32>"
    print_type_of(&"foo");          // prints "&str"}


查看完整回答
反对 回复 2019-07-13
?
侃侃无极

TA贡献2051条经验 获得超10个赞

如果事先知道所有类型,则可以使用特征添加type_of方法:

trait TypeInfo {
    fn type_of(&self) -> &'static str;}impl TypeInfo for i32 {
    fn type_of(&self) -> &'static str {
        "i32"
    }}impl TypeInfo for i64 {
    fn type_of(&self) -> &'static str {
        "i64"
    }}//...

没有复杂或没有‘,所以,虽然更有限,这是这里唯一的解决方案,得到一个字符串,是稳定的。但是,它非常辛苦,不考虑类型参数,所以我们可以.

trait TypeInfo {
    fn type_name() -> String;
    fn type_of(&self) -> String;}macro_rules! impl_type_info {
    ($($name:ident$(<$($T:ident),+>)*),*) => {
        $(impl_type_info_single!($name$(<$($T),*>)*);)*
    };}macro_rules! mut_if {
    ($name:ident = $value:expr, $($any:expr)+) => (let mut $name = $value;);
    ($name:ident = $value:expr,) => (let $name = $value;);}macro_rules! impl_type_info_single {
    ($name:ident$(<$($T:ident),+>)*) => {
        impl$(<$($T: TypeInfo),*>)* TypeInfo for $name$(<$($T),*>)* {
            fn type_name() -> String {
                mut_if!(res = String::from(stringify!($name)), $($($T)*)*);
                $(
                    res.push('<');
                    $(
                        res.push_str(&$T::type_name());
                        res.push(',');
                    )*
                    res.pop();
                    res.push('>');
                )*
                res            }
            fn type_of(&self) -> String {
                $name$(::<$($T),*>)*::type_name()
            }
        }
    }}impl<'a, T: TypeInfo + ?Sized> TypeInfo for &'a T {
    fn type_name() -> String {
        let mut res = String::from("&");
        res.push_str(&T::type_name());
        res    }
    fn type_of(&self) -> String {
        <&T>::type_name()
    }}impl<'a, T: TypeInfo + ?Sized> TypeInfo for &'a mut T {
    fn type_name() -> String {
        let mut res = String::from("&mut ");
        res.push_str(&T::type_name());
        res    }
    fn type_of(&self) -> String {
        <&mut T>::type_name()
    }}macro_rules! type_of {
    ($x:expr) => { (&$x).type_of() };}

让我们使用它:

impl_type_info!(i32, i64, f32, f64, str, String, Vec<T>, Result<T,S>)fn main() {
    println!("{}", type_of!(1));
    println!("{}", type_of!(&1));
    println!("{}", type_of!(&&1));
    println!("{}", type_of!(&mut 1));
    println!("{}", type_of!(&&mut 1));
    println!("{}", type_of!(&mut &1));
    println!("{}", type_of!(1.0));
    println!("{}", type_of!("abc"));
    println!("{}", type_of!(&"abc"));
    println!("{}", type_of!(String::from("abc")));
    println!("{}", type_of!(vec![1,2,3]));

    println!("{}", <Result<String,i64>>::type_name());
    println!("{}", <&i32>::type_name());
    println!("{}", <&str>::type_name());}

产出:

i32
&i32
&&i32
&mut i32
&&mut i32
&mut &i32
f64
&str
&&str
String
Vec<i32>
Result<String,i64>
&i32
&str

铁锈游乐场


查看完整回答
反对 回复 2019-07-13
?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

UPD以下内容不再有效。查帐舒布姆的回答为了改正。

检查std::intrinsics::get_tydesc<T>()..它现在处于“试验性”状态,但如果你只是对类型系统进行黑客攻击,那就没问题了。

请查看以下示例:

fn print_type_of<T>(_: &T) -> () {
    let type_name =
        unsafe {
            (*std::intrinsics::get_tydesc::<T>()).name        };
    println!("{}", type_name);}fn main() -> () {
    let mut my_number = 32.90;
    print_type_of(&my_number);       // prints "f64"
    print_type_of(&(vec!(1, 2, 4))); // prints "collections::vec::Vec<int>"}

这就是内部使用实施著名的{:?}格式化程序。


查看完整回答
反对 回复 2019-07-13
  • 4 回答
  • 0 关注
  • 2213 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信