Thông thường, mỗi nhánh trong biểu thức if
phải có cùng loại. Nếu loại đối với một số ngành được underspecified, trình biên dịch sẽ cố gắng để tìm ra loại phổ biến duy nhất:
fn print_number(x: int, y: int) {
let v = if x + y > 20 {
3 // this can be either 3u, 3i, 3u8 etc.
} else {
x + y // this is always int
};
println!("{}", v);
}
Trong mã này, 3
là underspecified nhưng else
chi nhánh lực lượng nó có các loại int
.
Điều này nghe có vẻ đơn giản: Có một chức năng "hợp nhất" hai hoặc nhiều loại thành loại phổ biến, hoặc nó sẽ cho bạn một lỗi khi điều đó là không thể. Nhưng nếu có một số fail!
trong chi nhánh thì sao?
fn print_number(x: int, y: int) {
let v = if x + y > 20 {
fail!("x + y too large") // ???
} else {
x + y // this is always int
};
println!("{}", v); // uh wait, what's the type of `v`?
}
Tôi muốn rằng fail!
không ảnh hưởng đến các chi nhánh khác, đó là trường hợp ngoại lệ. Vì mẫu này khá phổ biến trong Rust, khái niệm về loại phân tách đã được giới thiệu. Không có giá trị mà loại nào đang phân tách. (Nó cũng được gọi là "loại không có người ở" hoặc "loại trống" tùy thuộc vào ngữ cảnh. Không được nhầm lẫn với "loại đơn vị" có giá trị đơn là ()
.) Vì loại phân tách tự nhiên là tập hợp con của bất kỳ loại nào khác các loại, trình biên dịch kết luận rằng loại của v
chỉ là loại của chi nhánh else
, int
.
Return
biểu thức không khác với fail!
nhằm mục đích kiểm tra loại. Nó đột ngột thoát khỏi luồng thực hiện hiện tại giống như fail!
(nhưng không chấm dứt tác vụ, may mắn). Tuy nhiên, các loại phân kỳ không tuyên truyền để báo cáo kết quả tiếp theo:
fn print_number(x: int, y: int) {
let v = if x + y > 20 {
return; // this is diverging
() // this is implied, even when you omit it
} else {
x + y // this is always int
};
println!("{}", v); // again, what's the type of `v`?
}
Lưu ý rằng semicoloned tuyên bố duy nhất x;
tương đương với biểu thức x;()
. Thông thường a; b
có cùng loại với b
, vì vậy sẽ khá lạ khi x;()
có loại ()
chỉ khix
không phân kỳ và nó phân kỳ khi x
phân kỳ. Đó là lý do tại sao mã ban đầu của bạn không hoạt động.
Nó là hấp dẫn để thêm một trường hợp đặc biệt như thế:
- Tại sao bạn không làm cho
x;()
phân kỳ khi x
phân kì?
- Tại sao bạn không giả sử
uint
cho mỗi số nguyên không xác định bằng chữ khi loại của nó không thể suy ra? (Lưu ý: đây là trường hợp trong quá khứ.)
- Tại sao bạn không tự động tìm thấy siêu eo biển chung khi hợp nhất nhiều đối tượng đặc điểm?
Sự thật là, thiết kế hệ thống kiểu không khó, nhưng việc xác minh hệ thống khó hơn và chúng tôi muốn đảm bảo rằng hệ thống kiểu của Rust tương thích và lâu dài. Một số người trong số họ có thể xảy ra nếu nó thực sự hữu ích và nó được chứng minh là "đúng" cho mục đích của chúng tôi, nhưng không phải ngay lập tức.
Cách khác nhau? bạn có khác biệt gì khi không có dấu chấm phẩy? – sargas
Không có dấu chấm phẩy, các biểu thức 'trả về' và các biểu thức phân kỳ có vẻ tương thích với bất kỳ biểu thức nào và chúng dường như giữ lại đặc điểm đặc biệt đó ngay cả khi chúng được theo sau bởi dấu chấm phẩy. –
Đây chính xác là những gì họ đã nói với tôi tại kênh IRC. Về cơ bản, nó không tạo ra sự khác biệt nào cho kết quả cuối cùng (ít nhất là ví dụ của tôi), nhưng việc thêm dấu chấm phẩy có thể an tâm :) – sargas