2015-02-09 20 views
5

Rust'u öğrenmeye çalışıyorum ama yapmam gereken tek şey, duvara (benim için) tanıdık olan java konseptlerini tür sistemine çekmeye çalışmaktır. Ya da ayakkabı çekirdeği Haskell kavramları, vb için deneyin.Paylaşılan değişebilir durum nasıl temsil edilir?

Player ve birçok Resource s ile bir oyun yazmak istiyorum. Her Resource biri Player ait olabilir:

struct Player { 
    points: i32, 
} 

struct Resource<'a> { 
    owner: Option<&'a Player>, 
} 

fn main() { 
    let mut player = Player { points: 0 }; 
    let mut resources = Vec::new(); 
    resources.push(Resource { 
     owner: Some(&player), 
    }); 
    player.points = 30; 
} 

Ben oyuncuya kaynak noktasını olamaz çünkü değiştirerek aynı anda iken, derlemek değildir: Üstelik

error[E0506]: cannot assign to `player.points` because it is borrowed 
    --> src/main.rs:15:5 
    | 
13 |   owner: Some(&player), 
    |      ------ borrow of `player.points` occurs here 
14 |  }); 
15 |  player.points = 30; 
    |  ^^^^^^^^^^^^^^^^^^ assignment to borrowed `player.points` occurs here 

Resource, Player için değiştirilebilir bir başvuruya sahipse, aynı kullanıcıyla iki Resource s bile elde edemedim.

Bu gibi durumları çözmenin Pas yolu nedir?


Sorumu basitleştirilmiş ve Shepmaster cevabı buna bir doğru cevap ise (ne sordum ben gerçekten sormak istediği bu değildi çünkü), ben almak istedim bu değil. Onu yeniden yorumlamaya ve daha fazla bağlam eklemeye çalışacağım.

  1. kaynakları bir şekilde bağlanır - tüm kaynakların haritası (me) çizge oluşturur.
  2. Her oyuncu çok kaynağa sahip olabilir, her kaynak bir oyuncuya ait olabilir. Oyuncu kendi sahip olduğu kaynaklardan puan alabilmelidir. fn addPoints(&mut self, allResources: &ResourcesMap) ->() gibi bir imzayı düşündüm.
  3. Müzikçalardan birine bağlı olan bir kaynağı başka bir oyuncudan alabilir. Diğer oyuncu için bazı puan kaybıyla sonuçlanabilir.

sorunlar:

  1. ne (her bir düğüm birçok düğümlerden işaret edilebilir bir olasılıkla siklik yapı,) Rust bu grafik temsil etmek?
  2. Özgün sorun: Resource bir Player işaret ediyorsa, oynatıcıyı değiştiremem!

Player için Resource s nokta - çünkü, Oyuncu A'nın kaynakların bir kısmını başlamak çıkarmak oyuncu B'ye bir oyuncunun B kaynağa ve bu kaynaktan harita üzerinden hareket etmek olacaktır böyle bir işlem yapmak için doğal bir yol puanlar. Rust'ta doğal görünmüyor (en azından benim için).

cevap

6

cell documentation page oldukça iyi örnekler vardır. Pas hep (aynı şey iki değişken başvuruları olması gibi) kötü şeyler yapıyor sizi korumak için çalışacağız. Bunun öyle değil oldukça kullanma gibi "kolay" olarak Pas Diyelim ki çalışma zamanı denetimine yapmak gerekir beri yerleşik başvuruları, (Pas referanslar derleme sırasında kontrol edilir).

RefCell tipi sadece bunun için vardır. Bu çalışma zamanında mutability kurallarını denetler. Bazı bellek ve hesaplama zamanı yük oluşur, ancak Pas o derleme zamanı denetler var içinde vaat aynı bellek güvenliği ile bitirmek. RefCell taşıdık

Sizin örnek aşağıdaki gibi görünüyor. Sanırım zamanı güvenliğini derleme ödün vermeden Rust-yolla yapılabilir, Rust Java kodunu yazmaya çalışıyor yapmaya çalışıyorum ne olur

use std::cell::RefCell; 

struct Player { 
    points: i32, 
} 

// the lifetime is still needed to guarantee that Resources 
// don't outlive their player 
struct Resource<'a> { 
    owner: &'a RefCell<Player>, 
} 

impl<'a> Resource<'a> { 
    fn test(&self) -> i32 { 
     self.owner.borrow().points 
    } 
} 

fn main() { 
    let player = RefCell::new(Player { points: 0 }); 
    let mut resources = Vec::new(); 
    resources.push(Resource { owner: &player }); 
    player.borrow_mut().points = 30; 
    println!("{:?}", resources[0].test()); 
} 

Benim endişe nedir? Hiç değişken durumunu paylaşılan kaçının?

Sen derleme zamanlı güvenliğinden taviz verilmez. Pas Eğer kütüphaneleri doğru kullandığınız (derleme zamanında) emin olur. Eğer borrow* işlevleri kullanabilirsiniz Yine de, programınız zamanında panik olabilir. Bunun yerine try_borrow* işlevlerini kullanırsanız başarılı varsa, kontrol edebilir ve eğer bazı geri dönüş işlemini yapmak.

Ayrıca tip (Rc<RefCell<Player>>) bir RefCell bir referans sayılan kutusunu kullanabilirsiniz. O zaman sadece döngüleri oluşturmaz, ya da bellek serbest asla emin olmak gerekir. (Java otomatik döngüleri bulur rağmen) Bu gibi çok daha Java olurdu.

+0

iyi geliyor. Sanırım zamanı güvenliğini derleme ödün vermeden Rust-yolla yapılabilir, Rust Java kodunu yazmaya çalışıyor yapmaya çalışıyorum ne olur Beni ilgilendiren, nedir? Hiç değişken durumunu paylaşılan kaçının? –

+0

Not: derleme zamanlı güvenliğinden taviz verilmez. Pas Eğer kütüphaneleri doğru kullandığınız (derleme zamanında) emin olur. Eğer ödünç * işlevlerini kullanmak Yine de, programınız, zamanında panik olabilir. Eğer try_borrow * işlevlerini kullanın Bunun yerine, işlem başarılı olmuş, sen kontrol edebilir ve eğer bazı geri dönüş işlemini yapmak. –

+1

Ayrıca türe RefCell bir başvuru sayılan kutu (http://doc.rust-lang.org/std/rc/index.html) kullanabilir. O zaman sadece döngüleri oluşturmaz, ya da bellek serbest asla emin olmak gerekir. Bu gibi daha fazla Java olacaktır (Java otomatik döngüleri bulur rağmen) –

4

Her Kaynağın bir Player'a ait olabilir. tek Resource olması benim orijinal versiyonunu izin oyuncuların işaret için

struct Player { 
    points: i32, 
    resources: Vec<Resource>, 
} 

struct Resource { 
    gold: i32, 
} 

fn main() { 
    let player1 = Player { 
     points: 30, 
     resources: vec![Resource { gold: 54 }], 
    }; 
    let player2 = Player { 
     points: 50, 
     resources: vec![Resource { gold: 99 }], 
    }; 

    // If you really need an array of all the resources... 
    // Although this seems like you should just ask the Player to do something 
    let mut resources: Vec<_> = vec![]; 
    resources.extend(player1.resources.iter()); 
    resources.extend(player2.resources.iter()); 
} 

Düzenleme Teşekkür @ziggystar için:

tipleri o zaman bunu yapın. Artık oyuncular N kaynağına sahip olabilir, ancak hala bir kaynağın tek sahibi.

+2

Şimdi her oyuncu tam olarak bir kaynağın sahibi. Aynı değil. Ben bir şekilde bunu ifade, çünkü doğru cevap Bana verdiğin biri, ancak pek Rust anlayışıma ileriye beni taşır sorumu düzenlenmiş – ziggystar

+1

(soru okumadın mı). –

+0

bir yapı örneğini oluşturma kodu tarzı açısından tercih yolu nedir: 'Oyuncu {' veya 'Oyuncu {' (boşluk) ile? –

İlgili konular