Non-sözcüksel ömürleri ne anlama tarafından ne olduğunu anlamak için en kolay sözcük yaşamları bulunmaktadır. Sözcük dışı yaşam sürelerinden önceki Rust sürümlerinde bu kod başarısız olur:
fn main() {
let mut scores = vec![1, 2, 3];
let score = &scores[0];
scores.push(4);
}
Rust derleyicisi scores
bunun score
değişken tarafından ödünç alındığını görür , bu nedenle aşağıdakilerin daha fazla mutasyonuna izin vermez scores
:
error[E0502]: cannot borrow `scores` as mutable because it is also borrowed as immutable
--> src/main.rs:4:5
|
3 | let score = &scores[0];
| ------ immutable borrow occurs here
4 | scores.push(4);
| ^^^^^^ mutable borrow occurs here
5 | }
| - immutable borrow ends here
Ancak, insan trivially bu örnek aşırı muhafazakar olduğunu görebilirsiniz: score
edilir hiç kullanılmamış ! Problem ocağı olmasıdır scores
göre score
olan sözcük - bu yer aldığı bloğun sonuna kadar sürer:
fn main() {
let mut scores = vec![1, 2, 3];
let score = &scores[0];
scores.push(4);
}
Sözcüksel olmayan yaşam süreleri, derleyicinin bu ayrıntı düzeyini anlamasını sağlayarak bunu düzeltir. Derleyici artık bir ödünç almanın ne zaman gerekli olduğunu daha doğru bir şekilde söyleyebilir ve bu kod derlenecektir.
Sözcük dışı yaşamlarla ilgili harika bir şey, bir kez etkinleştirildiğinde, hiç kimsenin onlar hakkında düşünmeyeceğidir . Bu basitçe "Rust'un yaptığı" olacak ve işler (umarız) sadece işe yarayacak.
Sözcüksel yaşamlara neden izin verildi?
Rust, yalnızca bilinen güvenli programların derlenmesine izin vermek için tasarlanmıştır. Ancak, yalnızca güvenli programlara tam olarak izin vermek ve güvenli olmayanları reddetmek imkansızdır . Bu amaçla Rust, muhafazakar olma konusunda hata yapıyor: bazı güvenli programlar reddediliyor. Sözcüksel yaşamlar bunun bir örneğidir.
Sözcüksel yaşam sürelerinin derleyicide uygulanması çok daha kolaydı, çünkü blok bilgisi "önemsiz", veri akışı bilgisi ise daha az. Derleyicinin "orta düzey orta düzey gösterimi" (MIR) tanıtmak ve kullanmak için yeniden yazılması gerekiyordu . Daha sonra ödünç alma denetleyicisi ("ödünç" olarak da bilinir) soyut sözdizimi ağacı (AST) yerine MIR kullanmak için yeniden yazılmalıdır. Daha sonra, ödünç alma denetçisinin kurallarının daha ince taneli olması için düzeltilmesi gerekiyordu.
Sözcüksel yaşamlar her zaman programcının önüne geçmez ve sinir bozucu olsalar bile, sözlü yaşamlar etrafında çalışmanın birçok yolu vardır. Çoğu durumda, bu, fazladan küme parantezleri veya bir boole değeri eklemeyi içerir. Bu, Rust 1.0'ın leksik olmayan yaşam süreleri uygulanmadan önce uzun yıllar boyunca gönderilmesine ve yararlı olmasına izin verdi.
İlginç bir şekilde, sözcüksel yaşamlar nedeniyle bazı iyi kalıplar geliştirildi. Benim için enentry
önemli örnek modeldir . Bu kod, sözcüksel olmayan yaşam sürelerinden önce başarısız olur ve onunla derlenir:
fn example(mut map: HashMap<i32, i32>, key: i32) {
match map.get_mut(&key) {
Some(value) => *value += 1,
None => {
map.insert(key, 1);
}
}
}
Ancak bu kod, anahtarın karmasını iki kez hesapladığı için verimsizdir. Sözcük yaşam süreleri nedeniyle oluşturulan çözüm daha kısa ve daha etkilidir:
fn example(mut map: HashMap<i32, i32>, key: i32) {
*map.entry(key).or_insert(0) += 1;
}
"Sözcük dışı yaşamlar" adı bana doğru gelmiyor
Bir değerin yaşam süresi, değerin belirli bir bellek adresinde kaldığı zaman aralığıdır ( daha uzun bir açıklama için neden bir değeri ve bu değere başvuruyu aynı yapıda saklayamıyorum? Bölümüne bakın). Sözcük dışı yaşamlar olarak bilinen özellik , herhangi bir değerin yaşam süresini değiştirmez , bu nedenle yaşamları sözcüksel olmayan hale getiremez. Yalnızca bu değerlerin ödünç alanlarının izlenmesini ve kontrol edilmesini daha hassas hale getirir.
Özellik için daha doğru bir ad, "sözcüksel olmayan ödünç alanlar " olabilir. Bazı derleyici geliştiricileri, temelde yatan "MIR tabanlı ödünç verme" ye başvurur.
Sözcük dışı yaşamlar asla kendi başına "kullanıcıya dönük" bir özellik olarak tasarlanmadı . Yokluklarından aldığımız küçük kağıt kesiği yüzünden çoğunlukla zihnimizde büyüdüler. İsimleri çoğunlukla dahili geliştirme amaçlıydı ve pazarlama amacıyla değiştirmek asla bir öncelik değildi.
Evet ama nasıl kullanırım?
Rust 1.31'de (2018-12-06'da piyasaya sürüldü), Cargo.toml'nizde Rust 2018 sürümüne kaydolmanız gerekir:
[package]
name = "foo"
version = "0.0.1"
authors = ["An Devloper <an.devloper@example.com>"]
edition = "2018"
Rust 1.36'dan itibaren, Rust 2015 sürümü sözcüksel olmayan yaşam sürelerine de olanak tanır.
Sözcük dışı yaşam sürelerinin şu anki uygulaması bir "göç kipi" içindedir. NLL ödünç alma denetleyicisi geçerse, derleme devam eder. Aksi takdirde, önceki ödünç alma denetleyicisi çağrılır. Eski ödünç alma denetleyicisi koda izin verirse, size kodunuzun Rust'un gelecekteki bir sürümünde kırılma olasılığının yüksek olduğunu ve güncellenmesi gerektiğini bildiren bir uyarı yazdırılır.
Rust'un gecelik sürümlerinde, bir özellik bayrağı aracılığıyla zorunlu kırılmayı etkinleştirebilirsiniz:
#![feature(nll)]
Derleyici bayrağını kullanarak NLL'nin deneysel sürümüne bile katılabilirsiniz -Z polonius
.
Sözcüksel olmayan yaşam süreleri tarafından çözülen gerçek sorunların bir örneği