Şunlara sahibim:
let mut my_number = 32.90;
Nasıl yazdırabilirim my_number
?
Kullanarak type
ve type_of
işe yaramadı. Numaranın türünü yazdırabileceğim başka bir yol var mı?
Şunlara sahibim:
let mut my_number = 32.90;
Nasıl yazdırabilirim my_number
?
Kullanarak type
ve type_of
işe yaramadı. Numaranın türünü yazdırabileceğim başka bir yol var mı?
Yanıtlar:
Yalnızca bir değişkenin türünü öğrenmek istiyorsanız ve bunu derleme zamanında yapmaya hazırsanız, bir hataya neden olabilir ve derleyicinin onu almasını sağlayabilirsiniz.
Örneğin , değişkeni çalışmayan bir türe ayarlayın :
let mut my_number: () = 32.90;
// let () = x; would work too
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}`
Veya geçersiz bir yöntem çağırın :
let mut my_number = 32.90;
my_number.what_is_this();
error[E0599]: no method named `what_is_this` found for type `{float}` in the current scope
--> src/main.rs:3:15
|
3 | my_number.what_is_this();
| ^^^^^^^^^^^^
Veya geçersiz bir alana erişin :
let mut my_number = 32.90;
my_number.what_is_this
error[E0610]: `{float}` is a primitive type and therefore doesn't have fields
--> src/main.rs:3:15
|
3 | my_number.what_is_this
| ^^^^^^^^^^^^
Bunlar, bu durumda aslında tam olarak çözülmeyen türü ortaya çıkarır. Buna ilk örnekte “kayan nokta değişkeni” ve {float}
üç örnekte de “ ” denir ; bu, kısmen f32
ya da f64
nasıl kullandığınıza bağlı olarak çözülebilecek kısmen çözülmüş bir türdür . “ {float}
Ben tam olarak emin bu” ne değilim “o anlamına gelen bir yer tutucu olduğunu, yasal bir tür adı değil”, ama olan bir kayan nokta sayısı. Kayan nokta değişkenlerinde, kısıtlamazsanız, varsayılan olarak f64
¹ olur. (Niteliksiz bir tam sayı değişmez değeri varsayılan olarak kullanılır i32
.)
Ayrıca bakınız:
Still Derleyiciyi f32
ve arasında karar veremeyecek şekilde şaşırtmanın yolları olabilir f64
; Emin değilim. Eskiden olduğu kadar basitti 32.90.eq(&32.90)
, ama bu hem f64
şimdi hem de mutlu davranıyor , bu yüzden bilmiyorum.
ImageBuffer<_, Vec<_>>
, bu şeylerden birini parametre olarak alan bir işlev yazmaya çalıştığımda bana çok yardımcı olmayan bir şey beklediğini söyleyecektir . Ve bu ekleyene kadar derleyen kodda olur :()
. Daha iyi bir yol yok mu?
Her std::intrinsics::type_name
gece Rust yapısını kullanmak zorunda kalmanıza rağmen, bir türün adını alabileceğiniz kararsız bir işlev vardır (bu, istikrarlı Rust'da çalışmak için pek olası değildir). İşte bir örnek:
#![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"
}
#![feature(core_intrinsics)]
print_type_of
referansları (alıyor &T
) değil, değerleri ( T
sen geçmelidir böylece) &&str
yerine &str
; yani, print_type_of(&"foo")
yerine print_type_of("foo")
.
std::any::type_name
pas 1.38'den beri kararlı: stackoverflow.com/a/58119924
std::any::type_name
İşlevi kullanabilirsiniz . Bunun gece derleyicisine veya harici bir kasaya ihtiyacı yoktur ve sonuçlar oldukça doğrudur:
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}}
}
Uyarı: belgelerde belirtildiği gibi, bu bilgiler sadece hata ayıklama amacıyla kullanılmalıdır:
Bu, teşhis amaçlı kullanıma yöneliktir. Dizenin tam içeriği ve biçimi, türün en iyi çaba açıklaması olmak dışında belirtilmez.
Tür temsilcinizin derleyici sürümleri arasında aynı kalmasını istiyorsanız, phicr yanıtında olduğu gibi bir özellik kullanmalısınız .
Önceden tüm türleri biliyorsanız, type_of
yöntem eklemek için özellikleri kullanabilirsiniz :
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"
}
}
//...
İntrisik veya hiçbir şey yok, bu yüzden daha sınırlı olmasına rağmen, bu size bir ip ve istikrarlı olan tek çözümdür. (bkz. Fransız Boiethios'un cevabı ) Ancak, çok zahmetli ve tip parametrelerini hesaba katmıyor , bu yüzden ...
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() };
}
Kullanalım:
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());
}
çıktı:
i32
&i32
&&i32
&mut i32
&&mut i32
&mut &i32
f64
&str
&&str
String
Vec<i32>
Result<String,i64>
&i32
&str
UPD Aşağıdakiler artık çalışmıyor. Düzeltme için Shubham'ın cevabını kontrol edin .
Kontrol edin std::intrinsics::get_tydesc<T>()
. Şu anda "deneysel" durumda, ama sadece tip sistemi kesmek harikaydı.
Aşağıdaki örneği inceleyin:
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>"
}
Ünlü biçimlendiriciyi uygulamak için dahili olarak kullanılan budur {:?}
.
** GÜNCELLEME ** Bu son zamanlarda çalıştığı doğrulanmadı.
Vbo'nun cevabına dayanarak bunu yapmak için küçük bir sandık koydum. Size türü döndürmek veya yazdırmak için bir makro verir.
Bunu Cargo.toml dosyanıza koyun:
[dependencies]
t_bang = "0.1.2"
Sonra şöyle kullanabilirsiniz:
#[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"
}
#![feature]
kararlı yayın kanalında kullanılamaz`
İçindeki değişkeni kullanmanın basit yaklaşımını da kullanabilirsiniz println!("{:?}", var)
. Eğer Debug
türü için uygulanmadı, sen derleyici'nın hata iletisinde türünü görebilirsiniz:
mod some {
pub struct SomeType;
}
fn main() {
let unknown_var = some::SomeType;
println!("{:?}", unknown_var);
}
(çocuk parkı )
Kirli ama işe yarıyor.
Debug
uygulanmadı - bu olsa oldukça olası bir durumdur. Herhangi bir yapı için yapmanız gereken ilk şeylerden biri eklemektir #[derive(Debug)]
. Bence istemediğin Debug
zamanlar çok küçük.
println!("{:?}", unknown_var);
?? Bu bir dize enterpolasyonu ama neden :?
kıvrımlı parantezin içinde? @DenisKolodin
Debug
için kullandım , ama siz de kullanabilirsiniz {}
.
Bir @ChrisMorgan var cevabı istikrarlı pas içinde yaklaşık türünü almak için ( "şamandıra") ve bir @ShubhamJain var cevabı gece pas kararsız işlevi aracılığıyla kesin tipini ( "F64") alır.
Şimdi, kararlı pasta hassas tip (yani f32 ve f64 arasında karar verebilirsiniz)
fn main() {
let a = 5.;
let _: () = unsafe { std::mem::transmute(a) };
}
sonuç
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> main.rs:3:27
|
3 | let _: () = unsafe { std::mem::transmute(a) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `f64` (64 bits)
= note: target type: `()` (0 bits)
Güncelleme
Turbofish varyasyonu
fn main() {
let a = 5.;
unsafe { std::mem::transmute::<_, ()>(a) }
}
biraz daha kısa ama biraz daha az okunabilir.
float
arasındaki söylüyorum f32
ve f64
ile gerçekleştirilebilirstd::mem::size_of_val(&a)
Diğer bazı cevaplar işe yaramaz, ancak typename sandığının işe yaradığını görüyorum .
Yeni bir proje oluşturun:
cargo new test_typename
Cargo.toml dosyasını değiştirin
[dependencies]
typename = "0.1.1"
Kaynak kodunuzu değiştirin
use typename::TypeName;
fn main() {
assert_eq!(String::type_name(), "std::string::String");
assert_eq!(Vec::<i32>::type_name(), "std::vec::Vec<i32>");
assert_eq!([0, 1, 2].type_name_of(), "[i32; 3]");
let a = 65u8;
let b = b'A';
let c = 65;
let d = 65i8;
let e = 65i32;
let f = 65u32;
let arr = [1,2,3,4,5];
let first = arr[0];
println!("type of a 65u8 {} is {}", a, a.type_name_of());
println!("type of b b'A' {} is {}", b, b.type_name_of());
println!("type of c 65 {} is {}", c, c.type_name_of());
println!("type of d 65i8 {} is {}", d, d.type_name_of());
println!("type of e 65i32 {} is {}", e, e.type_name_of());
println!("type of f 65u32 {} is {}", f, f.type_name_of());
println!("type of arr {:?} is {}", arr, arr.type_name_of());
println!("type of first {} is {}", first, first.type_name_of());
}
Çıktı:
type of a 65u8 65 is u8
type of b b'A' 65 is u8
type of c 65 65 is i32
type of d 65i8 65 is i8
type of e 65i32 65 is i32
type of f 65u32 65 is u32
type of arr [1, 2, 3, 4, 5] is [i32; 5]
type of first 1 is i32
typename
, beyanda açık tip olmayan değişkenlerle çalışmaz. Soruyla birlikte çalıştırıldığında my_number
aşağıdaki hata " type_name_of
belirsiz sayısal tipte yöntem {float}
f32
0.65
ve iyi çalışıyor: type of c 0.65 0.65 is f64
. İşte benim sürüm:rustc 1.38.0-nightly (69656fa4c 2019-07-13)
Etkileşimli geliştirme sırasında değişkeninizin türünü bilmek istiyorsanız , editörünüzün veya ide'nizin içinde rls (pas dil sunucusu) kullanmanızı şiddetle tavsiye ederim . Ardından, fareyle üzerine gelme yeteneğini kalıcı olarak etkinleştirebilir veya değiştirebilirsiniz ve imlecinizi değişkenin üzerine getirebilirsiniz. Küçük bir diyalog türü dahil değişken hakkında bilgi gelmelidir.
:?
uzun bir süredir manuel olarak uygulanmaktadır. Ancak daha da önemlisi, sayı türleristd::fmt::Debug
için uygulama (bunun için kullanılan şeydir:?
) artık hangi tipte olduğunu gösteren bir sonek içermemektedir.