Pas'tam otomatik-kaldırma kuralları ne?
/Pas deneme öğreniyorum ve bu dilde bulduğum tüm zerafeti, beni şaşırtan bir özelliği olduğunu ve yersiz görünüyor tamamen.
Pas yöntem çağrıları yaparken otomatik olarak işaretçi çözümlemesi. Bazı testler kesin davranışlarını belirlemek için yaptım:
struct X { val: i32 }
impl std::ops::Deref for X {
type Target = i32;
fn deref(&self) -> &i32 { &self.val }
}
trait M { fn m(self); }
impl M for i32 { fn m(self) { println!("i32::m()"); } }
impl M for X { fn m(self) { println!("X::m()"); } }
impl<'a> M for &'a X { fn m(self) { println!("&X::m()"); } }
impl<'a, 'b> M for &'a &'b X { fn m(self) { println!("&&X::m()"); } }
impl<'a, 'b, 'c> M for &'a &'b &'c X { fn m(self) { println!("&&&X::m()"); } }
trait RefM { fn refm(&self); }
impl RefM for i32 { fn refm(&self) { println!("i32::refm()"); } }
impl RefM for X { fn refm(&self) { println!("X::refm()"); } }
impl<'a> RefM for &'a X { fn refm(&self) { println!("&X::refm()"); } }
impl<'a, 'b> RefM for &'a &'b X { fn refm(&self) { println!("&&X::refm()"); } }
impl<'a, 'b, 'c> RefM for &'a &'b &'c X { fn refm(&self) { println!("&&&X::refm()"); } }
struct Y { val: i32 }
impl std::ops::Deref for Y {
type Target = i32;
fn deref(&self) -> &i32 { &self.val }
}
struct Z { val: Y }
impl std::ops::Deref for Z {
type Target = Y;
fn deref(&self) -> &Y { &self.val }
}
struct A;
impl std::marker::Copy for A {}
impl M for A { fn m(self) { println!("A::m()"); } }
impl<'a, 'b, 'c> M for &'a &'b &'c A { fn m(self) { println!("&&&A::m()"); } }
impl RefM for A { fn refm(&self) { println!("A::refm()"); } }
impl<'a, 'b, 'c> RefM for &'a &'b &'c A { fn refm(&self) { println!("&&&A::refm()"); } }
fn main() {
// I'll use @ to denote left side of the dot operator
(*X{val:42}).m(); // i32::refm() , self == @
X{val:42}.m(); // X::m() , self == @
(&X{val:42}).m(); // &X::m() , self == @
(&&X{val:42}).m(); // &&X::m() , self == @
(&&&X{val:42}).m(); // &&&X:m() , self == @
(&&&&X{val:42}).m(); // &&&X::m() , self == *@
(&&&&&X{val:42}).m(); // &&&X::m() , self == **@
(*X{val:42}).refm(); // i32::refm() , self == @
X{val:42}.refm(); // X::refm() , self == @
(&X{val:42}).refm(); // X::refm() , self == *@
(&&X{val:42}).refm(); // &X::refm() , self == *@
(&&&X{val:42}).refm(); // &&X::refm() , self == *@
(&&&&X{val:42}).refm(); // &&&X::refm(), self == *@
(&&&&&X{val:42}).refm(); // &&&X::refm(), self == **@
Y{val:42}.refm(); // i32::refm() , self == *@
Z{val:Y{val:42}}.refm(); // i32::refm() , self == **@
A.m(); // A::m() , self == @
// without the Copy trait, (&A).m() would be a compilation error:
// cannot move out of borrowed content
(&A).m(); // A::m() , self == *@
(&&A).m(); // &&&A::m() , self == &@
(&&&A).m(); // &&&A::m() , self == @
A.refm(); // A::refm() , self == @
(&A).refm(); // A::refm() , self == *@
(&&A).refm(); // A::refm() , self == **@
(&&&A).refm(); // &&&A::refm(), self == @
}
Yani, bu, daha fazla veya daha az görünüyor:
- Derleyici gerektiği kadar başvuru operatörler bir yöntemi çağırmak için ekleyecektir.
- Yöntemleri
&self
(- by-call başvurusu) kullanarak ilan çözerken derleyici:- İlk
self
tek bir başvuru için seslendi - Sonra
self
tam tipi için seslendi - Sonra, başvuru operatörler birçok maç için gerekli olduğu kadar ekleme çalışır
- İlk
- Yöntemleri
self
kullanarak ilan (aramakopyaladeğeri) türüT
hareket halinde oldukları bildirildi kullanarak&self
(call-by-reference) türü&T
olarak başvurmak için ne varsa sol tarafındaki nokta operatörü. - Yukarıdaki kuralları ilk yerleşik kaldırma ham ile çalıştı ve eğer uyuşursa yok,
Deref
özelliği ile aşırı kullanılır.
Ancak, gerçekten gerçeklik maç görünmüyor - @87 **'deki yorum benim bu yanlış anlaşılma çözüldü.(&A).m()
çağırma açık &&&A
, aynı çalıştım ama işlem yapmayacak.
Tam otomatik-kaldırma kuralları nelerdir? Kimse böyle bir tasarım kararı için herhangi bir resmi gerekçe verebilir misiniz?
CEVAP
Kod pseudo çok fazla doğru. Bu örneğin, bir yöntem foo: T
** * * * 12 * çağrı aldık varsayalım. UFCS yöntemi, *örneğin 14* A::bar(&***foo)
ile çağrıldığını ne hakkında açık olmak için kullanacağım. Ben burada yazmak için bir yığın rastgele harfler, her biri sadece bazı keyfi tipi/özelliği dışında T
her zaman bu tür orijinal değişken foo
Bu yöntemi çağrılır.
Algoritma çekirdek:
- each "dereference step"
U
Her (U = T
olarak ayarlayın ve daha sonra 20*,...*)- eğer bir yöntem, alıcı türü (yöntemi
self
türü) tam olarakU
eşleştiğibar
eğer orada , (a "by value method") kullanın - aksi takdirde, ekleyin bir oto-ilan no (
&
&mut
alıcı), ve, eğer bazı yöntemin alıcı maçlar&U
kullanın (an "autorefd method")
- eğer bir yöntem, alıcı türü (yöntemi
Özellikle, her şeyi "" yöntemi, . alıcı türü olarak kabul etmektedir ^em>değilözelliği Self
türü, yani impl ... for Foo { fn method(&self) {} }
yöntemi eşleşen zaman &Foo
düşünür fn method2(&mut self)
eşleştirme &mut Foo
düşünmek istiyorum.
Eğer iç adımları (yani, sıfır ya da bir özellik yöntemleri 1 her biri için geçerli olabilir. birden fazla özellik yöntemleri geçerli eğer orada bir hata vardır ya da 2., ama tek geçerli her olabilir: 1 dan biri alınacak ilk olacak), ve doğal yöntemler özelliği olanlar önceliklidir. Ayrıca eğer eşleşen hiçbir şey bulamadan döngünün sonuna ulaşırsak bir hata. Ayrıca sonsuz döngü yapmak Deref
özyinelemeli uygulamaları için bir hatadır (vururlar "") özyineleme sınırı.
Bu kurallar görünmek için yapmak-ne-ben-yani en koşullara rağmen, sahip yeteneği yazmak için net UFCS form çok yararlı bazı kenar durumlarda, mantıklı hata iletileri için makro tarafından oluşturulan bir kod.
Sadece bir oto-başvuru nedeniyle eklenir
- eğer bağlı olsaydı, her tür başvuruları alınan rasgele bir sayı olabilir beri kötü/yavaş
- alarak bir referans
&foo
korur güçlü bir bağlantı içinfoo
(adresifoo
kendisi), ama daha fazla almaya başlar kaybetmek:&&foo
Adres bazıları geçici değişken yığında saklar&foo
.
Örnekler
Bir ara biz varsayalım eğer foo
türü varsa, 38**,:
X
başlıyoruzU = X
,refm
alıcı tipi&...
, Adım 1 de uymuyor, alarak otomatik ilan no verir bize&X
ve bu maç (Self = X
), çağrıRefM::refm(&foo)
- * *47, ilk adımda
&self
maçlarU = &X
(Self = X
) ile başlar ve aramaRefM::refm(foo)
&&&&&X
, bu uymuyor ya da adım (özellik değil uygulanan&&&&X
&&&&&X
), bu yüzden biz başvuru bir kez olsunU = &&&&X
hangi maçlar 1 (Self = &&&X
) ve aramaRefM::refm(*foo)
Z
, uymuyor ya adım çok başvuru yapıldı bir kez olsunY
, da uymuyor, o yüzden tekrar başvuru yapıldı,X
, yok maçı 1-maçtan sonra autorefing, o yüzden AraRefM::refm(&**foo)
.&&A
, 1. maç değil de 2 yapar. özelliği&A
(1) veya&&A
(2) için uygulanan olmadığından, maçlar&A
, 1. başvuru yapıldı,Self = A
ile
foo.m()
ve A
foo
türü: 69 *değil* değil varsayalım
A
U = A
aramaSelf = A
74 *doğrudanself
maçlar- * *76, 1. maç değil de 2 yapar. (ne
&A
ne&&A
uygulamak özelliği), yani başvuru yapıldıA
, maç, ancakM::m(*foo)
gerektirir alarakA
değer ve dolayısıyla hareketfoo
, dolayısıyla hata. - *, 1 *83. uymuyor, ama autorefing arama
Self = &&&A
M::m(&foo)
çok maç yapan&&&A
veriyor.
(Bu cevap* *91 is reasonably close to the (slightly outdated) README dayanmaktadır. Niko Matsakis, derleyici/dil bu bölümünün ana yazar, ayrıca bu cevabı göz önüne alın.)
Nasıl otomatik kaldırma Eclipse sondak...
Kuralları Javascript'ler otomatik...
Giriş arka plan kaldırma Chrome otomat...
UİTextView otomatik tespit edilen bağl...
Ve Heroku raylar 3: otomatik olarak &;...