我有以下内容:
let mut my_number = 32.90;
Run Code Online (Sandbox Code Playgroud)
我该如何打印my_number?
使用type并type_of没有奏效.还有其他方法可以打印数字的类型吗?
Chr*_*gan 159
如果您只想查找变量的类型并愿意在编译时执行此操作,则可能会导致错误并让编译器将其拾取.
例如,将变量设置为不起作用的类型({float}也可以):
let mut my_number: () = 32.90;
// let () = x; would work too
Run Code Online (Sandbox Code Playgroud)
error[E0308]: mismatched types
--> src/main.rs:2:29
|
2 | let mut my_number: () = 32.90;
| ^^^^^ expected (), found floating-point number
|
= note: expected type `()`
found type `{float}`
Run Code Online (Sandbox Code Playgroud)
let mut my_number = 32.90;
my_number.what_is_this();
Run Code Online (Sandbox Code Playgroud)
这些揭示了类型,在这种情况下实际上没有完全解决.它在第一个例子中称为"浮点变量",f32在所有三个例子中称为"" ; 这是一种部分解决的类型,可能会结束f64或{float}取决于您如何使用它." f64"不是合法的类型名称,它是占位符,意思是"我不完全确定这是什么",但它是一个浮点数.对于浮点变量,如果不限制它,它将默认为i32¹.(非限定整数文字将默认为f32.)
¹可能仍有一些方法让编译器感到困惑,因此它无法在f64和之间作出决定32.90.eq(&32.90); 我不确定.它曾经很简单f64,但是{float}现在和快乐地对待现在和chugs,所以我不知道.
小智 98
有一个不稳定的函数std::intrinsics::type_name可以让你得到一个类型的名称,虽然你必须使用每晚构建的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"
}
Run Code Online (Sandbox Code Playgroud)
phi*_*icr 49
如果您事先知道所有类型,则可以使用特征添加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"
}
}
//...
Run Code Online (Sandbox Code Playgroud)
没有内在或没什么',所以虽然更有限,但这是唯一的解决方案,让你一个字符串,并稳定.但是,这非常费力,并没有考虑类型参数,所以我们可以......
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() };
}
Run Code Online (Sandbox Code Playgroud)
我们来使用它:
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());
}
Run Code Online (Sandbox Code Playgroud)
输出:
i32
&i32
&&i32
&mut i32
&&mut i32
&mut &i32
f64
&str
&&str
String
Vec<i32>
Result<String,i64>
&i32
&str
Run Code Online (Sandbox Code Playgroud)
vbo*_*vbo 18
UPD以下不再适用.查看Shubham的答案以便纠正.
退房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>"
}
Run Code Online (Sandbox Code Playgroud)
这是内部用于实现着名{:?}格式化程序的内容.
Fre*_*ios 14
您可以使用该std::any::type_name功能。不需要夜间编译器或外部包装箱,结果非常正确:
fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = "Hello";
let i = 42;
print_type_of(&s); // &str
print_type_of(&i); // i32
print_type_of(&main); // playground::main
print_type_of(&print_type_of::<i32>); // playground::print_type_of<i32>
print_type_of(&{ || "Hi!" }); // playground::main::{{closure}}
}
Run Code Online (Sandbox Code Playgroud)
mpi*_*olo 13
根据vbo的回答,我把一个小箱子放在一起做这个.它为您提供了一个返回或打印出类型的宏.
把它放在你的Cargo.toml文件中:
[dependencies]
t_bang = "0.1.2"
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它:
#[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"
}
Run Code Online (Sandbox Code Playgroud)
Tan*_*lam 10
1.38版本新增std::any::type_name
use std::any::type_name;
fn type_of<T>(_: T) -> &'static str {
type_name::<T>()
}
fn main() {
let x = 21;
let y = 2.5;
println!("{}", type_of(&y));
println!("{}", type_of(x));
}
Run Code Online (Sandbox Code Playgroud)
小智 8
trait function 怎么样type_name,它有助于快速获取类型名称。
pub trait AnyExt {
fn type_name(&self) -> &'static str;
}
impl<T> AnyExt for T {
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
}
fn main(){
let my_number = 32.90;
println!("{}",my_number.type_name());
}
Run Code Online (Sandbox Code Playgroud)
输出:
f64
Run Code Online (Sandbox Code Playgroud)
我写了一个宏type_of!()来调试,它是原始的 std dbg!()。
pub trait AnyExt {
fn type_name(&self) -> &'static str;
}
impl<T> AnyExt for T {
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
}
fn main(){
let my_number = 32.90;
println!("{}",my_number.type_name());
}
Run Code Online (Sandbox Code Playgroud)
输出:
[src/main.rs:32] 32.90: f64
[src/main.rs:33] my_number: f64
Run Code Online (Sandbox Code Playgroud)
您还可以使用使用变量的简单方法println!("{:?}", var).如果Debug没有为类型实现,您可以在编译器的错误消息中看到类型:
mod some {
pub struct SomeType;
}
fn main() {
let unknown_var = some::SomeType;
println!("{:?}", unknown_var);
}
Run Code Online (Sandbox Code Playgroud)
(围栏)
它很脏但是有效.
有一个 @ChrisMorgan答案可以在稳定的 rust 中获得近似类型(“float”),有一个 @ShubhamJain答案可以通过夜间 rust 中的不稳定函数获得精确类型(“f64”)。
现在有一种方法可以在稳定的 Rust 中获得精确的类型(即在 f32 和 f64 之间做出决定):
fn main() {
let a = 5.;
let _: () = unsafe { std::mem::transmute(a) };
}
Run Code Online (Sandbox Code Playgroud)
结果是
fn main() {
let a = 5.;
let _: () = unsafe { std::mem::transmute(a) };
}
Run Code Online (Sandbox Code Playgroud)
更新
涡轮鱼的变种
fn main() {
let a = 5.;
unsafe { std::mem::transmute::<_, ()>(a) }
}
Run Code Online (Sandbox Code Playgroud)
稍微短一些,但可读性稍差。
如果您只是想在交互式开发过程中了解变量的类型,我强烈建议您在编辑器或 IDE 中使用rls (Rust 语言服务器)。然后,您可以简单地永久启用或切换悬停功能,并将光标放在变量上。一个小对话框应该会显示有关变量的信息,包括类型。
| 归档时间: |
|
| 查看次数: |
58167 次 |
| 最近记录: |