2017-11-05 18 views
5

Tôi đang cố gắng sắp xếp một Vec<String> bằng cách sử dụng một hàm quan trọng trả về tham chiếu đến các chuỗi trong vectơ. Một ví dụ giả tạo là để sử dụng chức năng nhận dạng như là chức năng quan trọng (trong đó tất nhiên là vô dụng, nhưng đó là ví dụ nhỏ để tái tạo vấn đề của tôi):Tại sao tôi không thể sử dụng một hàm quan trọng trả về tham chiếu khi sắp xếp một vectơ với sort_by_key?

fn key(x: &String) -> &String { 
    x 
} 

Ngay bây giờ cho items: Vec<String>, tôi muốn để có thể làm

items.sort_by_key(key); 

này cung cấp cho các lỗi sau:

error[E0271]: type mismatch resolving `for<'r> <fn(&std::string::String) -> &std::string::String {main::key} as std::ops::FnOnce<(&'r std::string::String,)>>::Output == _` 
    --> src/main.rs:19:11 
    | 
19 |  items.sort_by_key(key); 
    |   ^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime 
    | 
    = note: concrete lifetime that was found is lifetime '_#16r 

tôi không hiểu tại sao tôi nhận được lỗi này, vì vậy tôi đã cố gắng để theo dõi này xuống. đầu tiên tôi thực hiện phiên bản riêng của tôi về sort_by_key():

fn sort_by_key<T, K: Ord>(a: &mut [T], key: fn(&T) -> K) { 
    a.sort_by(|x, y| key(x).cmp(&key(y))); 
} 

Khi cố gắng để gọi chức năng này, tôi nhận được những gì trông giống như lỗi "ngược":

error[E0308]: mismatched types 
    --> src/main.rs:22:29 
    | 
22 |  sort_by_key(&mut items, key); 
    |        ^^^ expected concrete lifetime, found bound lifetime parameter 
    | 
    = note: expected type `fn(&std::string::String) -> _` 
       found type `fn(&std::string::String) -> &std::string::String {main::key}` 

tôi có thể làm cho mã biên dịch này bằng cách sửa chữa các loại chìa khóa để &T thay vì sử dụng các tham số chung K, hoặc bằng cách sử dụng &K thay vì K như kiểu trả về cho hàm chính:

fn sort_by_key_v2<T: Ord>(a: &mut [T], key: fn(&T) -> &T) { 
    a.sort_by(|x, y| key(x).cmp(&key(y))); 
} 
fn sort_by_key_v3<T, K: Ord>(a: &mut [T], key: fn(&T) -> &K) { 
    a.sort_by(|x, y| key(x).cmp(&key(y))); 
} 

Tôi cũng đã thử thêm chú thích trọn đời, nhưng điều đó chỉ thay đổi lỗi xung quanh mà không giải quyết lỗi đó.

Here's the three versions of the sort_by_key() function on the Playground.

Tại sao tôi gặp phải các lỗi này? Có cách nào để sửa chữa chúng trong khi vẫn giữ loại khóa K hoàn toàn chung chung không?

+0

Tôi khuyên bạn nên đặt lại câu hỏi để tránh một điều tra quan trọng như vậy. Ngoài ra, bạn có thể cung cấp một MCVE về nỗ lực đầu tiên của bạn, tốt hơn là một cái gì đó tái tạo vấn đề trong Rust Playground? –

+0

@ E_net4 Tôi đã thêm liên kết sân chơi và chỉ cần xóa câu hỏi cuối cùng. Tôi nghĩ rằng nó hoàn toàn chấp nhận được để hỏi nhiều hơn một câu hỏi trong một bài miễn là chúng phụ thuộc vào nhau. –

+0

@ E_net4 Tôi đã theo dõi lời khuyên của bạn và xóa bỏ điều tra. Câu hỏi của tôi về cơ bản là lý do tại sao tôi nhận được các lỗi và cách khắc phục chúng. –

Trả lời

5

Why am I getting these errors? Is there any way to fix them?

Nguyên nhân và sửa lỗi giống nhau: Rust đơn giản là không thể hiện đủ để thể hiện những gì bạn muốn. Tính năng cần thiết được gọi là generic associated types (GATs); trước đây được gọi là nhà xây dựng loại liên quan (ATC) hoặc loại có mức độ cao hơn (HKT).

Từ associated issue:

For the sort_by_key call to be okay, the lifetime of the input reference [...] needs to be incorporated into B to make the return type &'a str , but B is a type parameter.

Tôi không biết nếu chữ ký cho sort_by_key sẽ có thể được liên tục di chuyển đến một GAT khi chúng được thực hiện.


Còn bây giờ, bạn phải sử dụng "dài" hình thức:

v.sort_by(|x, y| key(x).cmp(&key(y))); 
+0

Cảm ơn, tôi đã nghi ngờ điều đó là không thể. Tôi sẽ đọc RFC được liên kết để hiểu được thông báo lỗi có ý nghĩa gì và tại sao thông báo lỗi cho phương thức lại khác với thông báo tôi nhận được cho phiên bản của riêng mình. –

2

Như @Shepmaster explained bạn không thể có một chức năng sort_by_key xử lý kiếp sống liên quan đến chung cho các kiểu trả về của key chức năng, nhưng ở đây là một biến thể cho một hàm quan trọng luôn trả lại tham chiếu:

fn sort_by_key_ref<T, F, K>(a: &mut [T], key: F) 
where 
    F: Fn(&T) -> &K, 
    K: ?Sized + Ord, 
{ 
    a.sort_by(|x, y| key(x).cmp(key(y))); 
} 

Bạn cũng có thể ghi lại yêu cầu suốt đời đối với chức năng chính:

for<'a> F: Fn(&'a T) -> &'a K, 

Xem example on playground.

+0

Cảm ơn, tôi đã tìm ra điều đó (xem phiên bản thứ ba trong câu hỏi của tôi). Tôi vẫn muốn hiểu chính xác những thông báo lỗi có ý nghĩa gì. –

+0

Huh, hoàn toàn bỏ lỡ điều đó, xin lỗi. Ít nhất phần '? Sized' thêm một cái gì đó mới :) – Stefan

Các vấn đề liên quan