Pertanyaan Menggunakan .into () ketika inferensi jenis tidak mungkin


Saya berharap bisa menggunakannya .into() untuk mengkonversi nilai dalam konteks di mana inferensi tipe tidak mungkin. Ini biasanya ketika saya ingin mengubah nilai sementara menjadi beberapa jenis lain untuk meneruskannya ke fungsi umum. Lihat kode berikut untuk contoh (tempat bermain):

use std::convert::*;

struct NewType(pub i32);

impl From<NewType> for i32 {
    fn from(src: NewType) -> i32 { src.0 }
}

fn main() {
    let a = NewType(5);
    println!("{}", a.into()); // Understandably won't compile
}

Bagaimana cara memberitahu kompiler yang ingin saya ubah a ke i32?

Saya bisa membuatnya bekerja dengan benar dengan memberi makan secara eksplisit Into dengan argumen tipe; Into::<i32>::into(a) Ini lebih verbose dan eksplisit daripada yang saya harapkan dapat dicapai, terutama dalam konteks di mana saya belum mengimpor Into (std::convert::Into::<i32>::into(a)). a.into::<i32>() akan diterima, tetapi itu bukan di mana argumen jenis pergi.

a.into() as i32 akan terlihat bagus, tetapi sintaksis ini tidak berfungsi.

Apakah ada trik yang saya lewatkan?


5
2017-12-18 11:27


asal


Jawaban:


Anda bisa menggunakannya from:

use std::convert::*;

struct NewType(pub i32);

impl From<NewType> for i32 {
    fn from(src: NewType) -> i32 { src.0 }
}

fn main() {
    let a = NewType(5);
    println!("{}", i32::from(a));
}

Anda dapat membaca lebih lanjut tentang ini di sini: https://doc.rust-lang.org/1.11.0/std/convert/index.html


6
2017-12-18 11:49



Rupanya, ini mungkin terjadi pada Rust setiap malam jenis anggapan, yang tampaknya menjadi fitur yang dirancang untuk kasus penggunaan ini (tempat bermain):

#![feature(type_ascription)]

use std::convert::*;

struct NewType(pub i32);

impl From<NewType> for i32 {
    fn from(src: NewType) -> i32 { src.0 }
}

fn main() {
    let a = NewType(5);
    println!("{}", a.into() : i32);
}

Karena ini tersedia dalam fitur eksperimental, mungkin masuk akal untuk menyimpulkan bahwa itu hilang dari bahasa yang tepat?


5
2017-12-18 11:44



Saya tidak berpikir ada cara yang lebih baik. Karena parameter tipe ada pada sifat, bukan metodenya into(), operator turbofish into::<i32>() tidak berfungsi. Seperti yang Anda katakan, Anda dapat membuatnya bekerja dengan menggunakan UFCS:

Into::<i32>::into(a)

Perhatikan itu Into diekspor kembali std::prelude, yang berarti bahwa Anda tidak perlu menentukan jalur lengkap, karena sifat selalu dalam lingkup.

Tentu saja, ada juga selalu kemungkinan untuk mengikat sementara Anda ke nama dan menggunakan tipe anotasi let-mengikat:

let tmp: i32 = a.into();

Mungkin lebih baik di masa depan! Ada sebuah Ketik Asumsi untuk Ekspresi RFC, yang sudah diterima dan diimplementasikan. Fitur ini masih tidak stabil, tetapi jika diimplementasikan Anda bisa menulis sesuatu seperti:

println!("{}", (a.into(): i32));   // still unstable :/

4
2017-12-18 11:45



Anda cukup menganotasi jenis hasil dengan menugaskannya ke variabel.

let b: i32 = a.into();
println!("{}", b);

0
2017-12-18 11:40