rust - How to reference multiple members in an array? -
i have array of 2 players. have variable, current_num equal player in array current player. have while loop iterates through main game logic current_num updated, stays same. assigned current_player , next_player variable each iteration of loop so:
while !self.board.check_win() { let ref mut current_player = self.players[current_num]; let ref mut next_player = self.players[(current_num+1)%2]; /* game logic */ }
this doesn't work because try borrow self.players[..] twice. don't need next_player variable if somehow store next player inside first player object, can't create cyclic data structures in rust seems. fought hard compiler accomplish following:
player1.next = &player2; player2.next = &player1;
unfortunately doesn't seem possible.... if is, rather along lines of:
current_player.next().do_something();
instead of needing next_player variable. able do:
current_player = current_player.next();
for switching next player wouldn't have keep index variable (current_num).
now have working mode refer current player as:
self.players[current_num].do_something() //current_player self.players[(current_num+1)%2).do_something() //next_player
this avoids borrowing issues, makes verbose code that's hard read. c/c++ easier regards getting kind of design working. feel i'm fighting compiler want done...
any appreciated!
to solve immediate problem can use the mut_split_at
method, uses unsafe
code internally give 2 disjoint slices vector, resolving borrowing issues. might write wrapper like:
fn double_index<'a, t>(x: &'a mut [t], i: uint, j: uint) -> (&'a mut t, &'a mut t) { assert!(i != j, "cannot double_index equal indices"); if < j { let (low, hi) = x.mut_split_at(j); (&mut low[i], &mut hi[0]) } else { // > j let (low, hi) = x.mut_split_at(i); (&mut hi[0], &mut low[j]) } }
then write
let (current_player, next_player) = double_index(self.players, current_num, (current_num + 1) % 2);
(assuming self.players
[player, .. 2]
or &mut [player]
. if vec<player>
need call .as_mut_slice()
explicitly.)
you can't create cyclic data structures in rust seems
you can, using rc
, weak
. shared mutability, you'll need use refcell
or cell
. e.g.
use std::rc::{rc, weak}; use std::cell::refcell; struct player { // ... next: option<weak<refcell<player>>> } impl player { fn next(&self) -> rc<refcell<player>> { // upgrade goes weak rc & fails if invalid self.next.unwrap().upgrade() } } let player1 = rc::new(refcell::new(player { ..., next: none })); let player2 = rc::new(refcell::new(player { ..., next: none })); // join them up; downgrade goes rc weak player1.borrow_mut().next = some(player2.downgrade()); player2.borrow_mut().next = some(player1.downgrade());
this avoids borrowing issues, makes verbose code that's hard read. c/c++ easier regards getting kind of design working. feel i'm fighting compiler want done...
any sort of shared mutability easy wrong; , in languages without gc, can lead dangling pointers, segfaults & security holes. unfortunately sealing holes in manner rust leads type of thing being rather ugly @ times.
Comments
Post a Comment