Pertanyaan Bagaimana cara mengembalikan & Jalur dari suatu fungsi?


Saya mencoba memahami bagaimana menulis kode Rust yang tepat, tetapi saya pikir saya mungkin melebih-lebihkan kekuatan kemampuan kompiler untuk memahami masa hidup objek saya. Ini adalah kode yang saya harapkan dapat berfungsi:

use std::path::Path;
use std::env;
use rusqlite::SqliteConnection;

struct SomeDatabase {
    conn: SqliteConnection,
}

impl SomeDatabase {
    fn getPath() -> &Path {
        let path = env::home_dir().unwrap();
        path.push("foo.sqlite3");
        path.as_path()
    }

    fn open() -> SomeDatabase {
        let path = SomeDatabase::getPath()
        SomeDatabase { conn: SqliteConnection::open(path).unwrap() }
    }
}

fn main() {
    let db = SomeDatabase::open();
}

Ketika saya mencoba untuk mengkompilasi ini, saya mendapatkan kesalahan tentang specifier seumur hidup yang hilang &Path. Saya tahu jika ini mengambil parameter referensi dari pemanggil, itu akan memakan waktu seumur hidup yang sama seperti referensi itu. Di sini meskipun apa yang saya harapkan adalah bahwa seumur hidup akan melekat pada variabel yang saya berikan hasilnya.

Saya tahu kehidupan dapat ditambahkan secara eksplisit, tetapi saya tidak tahu bagaimana menerapkannya dalam kasus ini. Compiler menyarankan mencoba 'static seumur hidup, tetapi itu tidak masuk akal di sini sejauh yang saya tahu karena sumber nilai pengembalian fungsi ini tidak statis.

Sekarang, hanya untuk mencoba melihat apa yang terjadi jika saya mencoba mengkompilasi sisa kode, saya mengubah jenis kembalinya dari &Path untuk PathBuf dan dipanggil as_path() di open(). Ini menyebabkan kompiler untuk menampilkan kesalahan ini:

src\main.rs:22:30: 22:52 error: the trait `core::marker::Sized` is not implemented for the type `[u8]` [E0277]
src\main.rs:22         SomeDatabase { conn: SqliteConnection::open(path).unwrap() }
                                            ^~~~~~~~~~~~~~~~~~~~~~
src\main.rs:22:30: 22:52 note: `[u8]` does not have a constant size known at compile-time
src\main.rs:22         SomeDatabase { conn: SqliteConnection::open(path).unwrap() }
                                            ^~~~~~~~~~~~~~~~~~~~~~

SqliteConnection::open() mengembalikan a Result<SqliteConnection, SqliteError> dan satu-satunya bidang di dalamnya SqliteConnection adalah RefCell, jadi saya tidak mengerti di mana kesalahan ini tentang array byte berasal.

Jadi, mengapa tidak bekerja seperti yang saya harapkan dan apa cara paling Rusty untuk menulis kode ini?


5
2017-09-06 01:44


asal


Jawaban:


Dalam kasus pertama Anda, Anda membuat nilai dan kemudian mencoba mengembalikan referensi ke dalamnya. Tetapi karena Anda tidak menyimpan nilai itu di mana pun, ia akan hancur setelah fungsi berakhir. Jika diizinkan, itu akan menjadi bug yang bisa digunakan setelah bebas.

Alasan menyarankan untuk mengembalikan &'static Path adalah karena fungsi tidak diparameterisasi selama masa kehidupan apa pun, sehingga satu-satunya masa pakai yang Anda dapat pastikan hidup lebih lama dari apa pun yang ingin menggunakan nilai pengembalian adalah 'static.

Anda benar bahwa Anda perlu mengembalikan PathBuf langsung bukan &Path.

Saya tidak yakin mengapa Anda mendapatkan [u8] kesalahan berukuran.

Anda tidak perlu memanggil "as_path ()" sama sekali. SqliteConnection::open mengambil nilai yang diimplementasikan AsRef<Path> (AsRef adalah semacam suka Into), dan PathBuf tidak menerapkan sifat itu.


7
2017-09-06 02:21