rustwasm / book

The Rust and WebAssembly Book
https://rustwasm.github.io/docs/book/
MIT License
1.73k stars 208 forks source link

Incomplete Conway's Game of Life example #165

Closed rapodaca closed 5 years ago

rapodaca commented 5 years ago

Where in the docs did you come across this?

https://rustwasm.github.io/docs/book/game-of-life/implementing.html

Describe what about it does not make sense

The example code does not appear complete enough to compile.

Why does it not make sense?

  1. top declarations appear to be missing
  2. an implementation of to_string does not appear to have been given

How could we improve it?

It would be nice to see a complete listing for the file lib.rs at the end of the page found at:

https://rustwasm.github.io/docs/book/game-of-life/implementing.html

I'm not sure if I just missed something or if documentation is in fact missing. Here's what I have for lib.rs just at:

With that, the Rust half of our Game of Life implementation is complete!

Recompile it to WebAssembly by running wasm-pack build within the wasm-game-of-life directory.

mod utils;

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Cell {
    Dead = 0,
    Alive = 1,
}

#[wasm_bindgen]
pub struct Universe {
    width: u32,
    height: u32,
    cells: Vec<Cell>,
}

#[wasm_bindgen]
impl Universe {
    pub fn new() -> Universe {
        let width = 64;
        let height = 64;

        let cells = (0..width * height)
            .map(|i| {
                if i % 2 == 0 || i % 7 == 0 {
                    Cell::Alive
                } else {
                    Cell::Dead
                }
            })
            .collect();

        Universe {
            width,
            height,
            cells,
        }
    }

    pub fn render(&self) -> String {
        self.to_string()
    }

    // pub fn render(&self) -> String {
    //     self.to_string()
    // }

    fn get_index(&self, row: u32, column: u32) -> usize {
        (row * self.width + column) as usize
    }

    fn live_neighbor_count(&self, row: u32, column: u32) -> u8 {
        let mut count = 0;

        for delta_row in [self.height - 1, 0, 1].iter().cloned() {
            for delta_col in [self.width - 1, 0, 1].iter().cloned() {
                if delta_row == 0 && delta_col == 0 {
                    continue;
                }

                let neighbor_row = (row + delta_row) % self.height;
                let neighbor_col = (column + delta_col) % self.width;
                let idx = self.get_index(neighbor_row, neighbor_col);
                count += self.cells[idx] as u8;
            }
        }

        count
    }

    pub fn tick(&mut self) {
        let mut next = self.cells.clone();

        for row in 0..self.height {
            for col in 0..self.width {
                let idx = self.get_index(row, col);
                let cell =self.cells[idx];
                let live_neighbors = self.live_neighbor_count(row, col);

                let next_cell = match (cell, live_neighbors) {
                    (Cell::Alive, x) if x < 2 => Cell::Dead,
                    (Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive,
                    (Cell::Alive, x) if x > 3 => Cell::Dead,
                    (Cell::Dead, 3) => Cell::Alive,
                    (otherwise, _) => otherwise,
                };

                next[idx] = next_cell;
            }
        }

        self.cells = next;
    }
}

My error is:

wasm-game-of-life$ wasm-pack build [INFO]: 🎯 Checking for the Wasm target... [INFO]: 🌀 Compiling to Wasm... Compiling wasm-game-of-life v0.1.0 (/Users/rich/tmp/wasm-game-of-life) error[E0599]: no method named to_string found for type &Universe in the current scope --> src/lib.rs:44:14 44 self.to_string() ^^^^^^^^^

= note: the method to_string exists but the following trait bounds were not satisfied: &Universe : std::string::ToString Universe : std::string::ToString = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item to_string, perhaps you need to implement it: candidate #1: std::string::ToString

error: aborting due to previous error

For more information about this error, try rustc --explain E0599. error: Could not compile wasm-game-of-life.

To learn more, run the command again with --verbose. Error: Compiling your crate to WebAssembly failed Caused by: failed to execute cargo build: exited with exit code: 101

fitzgen commented 5 years ago

Did you include the code to implement std::fmt::Display? The ToString trait is implemented for all T where T: Display:

By implementing the Display trait from Rust's standard library, we can add a way to format a structure in a user-facing manner. This will also automatically give us a to_string method.

use std::fmt;

impl fmt::Display for Universe {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for line in self.cells.as_slice().chunks(self.width as usize) {
            for &cell in line {
                let symbol = if cell == Cell::Dead { 'â—»' } else { 'â—¼' };
                write!(f, "{}", symbol)?;
            }
            write!(f, "\n")?;
        }
        Ok(())
    }
}

If you include that code, it should resolve those errors you are seeing.

fitzgen commented 5 years ago

Closing this. Feel free to reopen if you need further help. Thanks!