如何在Rust中打印variables的types?
我有这个代码片段:
let mut my_number=32.90;
我需要知道my_number
的types。 使用type
和type_of
不起作用; 有什么其他方法可以打印数字的types?
如果你只想找出一个variables的types,并且愿意在编译时做这个variables,那么你可能会导致一个错误,让编译器把它捡起来。
例如, 将variables设置为不起作用的types ( 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
这些揭示了在这种情况下实际上没有完全解决的types。 它在第一个例子中被称为“浮点variables”,在所有三个例子中被称为“ {float}
”; 这是一个部分解决的types,可能会结束f32
或f64
,这取决于你如何使用它。 “ {float}
”不是一个合法的types名称,它是一个占位符,意思是“我不完全确定这是什么”,但它是一个浮点数。 在浮点variables的情况下,如果不约束它,它将默认为f64
。 (一个不合格的整数字面量将默认为i32
。)
¹编译器可能仍然存在一些问题,以至于无法在f32
和f64
之间做出决定。 我不确定。 它曾经是32.90.eq(&32.90)
那样简单,但是现在把它当作f64
并且愉快地f64
,所以我不知道。
有一个不稳定的函数std::intrinsics::type_name
可以得到一个types的名字,但是你必须使用每晚构build的Rust(这个不太可能在稳定的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" }
UPD以下不起作用了。 检查Shubham的更正答案 。
检查出std::intrinsics::get_tydesc<T>()
。 现在它处于“实验”状态,但是如果你只是在types系统中进行黑客攻击,那也没关系。
看看下面的例子:
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>" }
这是内部用来实现着名的{:?}
格式化程序的东西。
如果事先知道所有的types,你可以使用traits来添加一个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" } } //...
没有内疚或没什么,所以虽然更有限这是唯一的解决scheme,让你一个string,是稳定的。 然而,这是非常费力的,不考虑types参数,所以我们可以…
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_type_info!(i32, i64, f32, f64, str, String, Vec<T>, Result<T,S>); fn main() { println!("{}", 1.type_of()); println!("{}", 1.0.type_of()); println!("{}", "abc".type_of()); println!("{}", String::from("abc").type_of()); println!("{}", vec![1,2,3].type_of()); println!("{}", Result::<String,i64>::type_name()) }
输出:
i32 f64 str String Vec<i32> Result<String,i64>
铁锈游乐场
我放了一个小箱子,根据vbo的回答做到这一点。 它给你一个macros来返回或打印出types。
把它放在你的Cargo.toml文件中:
[dependencies] t_bang = "0.1.2"
那么你可以这样使用它:
#[macro_use] extern crate t_bang; use t_bang::*; fn main() { let x = 5; let x_type = t!(x); println!("{:?}", x_type); // prints out: "i32" pt!(x); // prints out: "i32" pt!(5); // prints out: "i32" }
您也可以使用在println!("{:?}", var)
中使用variables的简单方法。 如果Debug
types没有实现,你可以在编译器的错误信息中看到types:
mod some { pub struct SomeType; } fn main() { let unknown_var = some::SomeType; println!("{:?}", unknown_var); }
( 围栏 )
这是肮脏的,但它的作品。