Learning to program in RUST, together

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Learning to program in RUST, together

Post by Michael Sherwin »

For those that want to investigate this new programming language let's begin. I downloaded RUSTC the Rust compiler, Cargo the Rust project manager, the Atom programming editor and a Rust package for atom. Somehow I got it all working.

Rust would seem to have quite a few advantages for chess programming like speed, data safety and maybe simpler SMP with race condition safety. And other advantages. You can research that for yourselves.

The downside (or another upside) to Rust is that it is very strict and so the flexibility of C is lost. If it is an upside then it is because certain mistakes are caught at compile time rather than crash the program at run time.

I have written some sample code that looks like the beginning of a chess program. Well I hope it is anyway. It compiles without warning or errors and does what it is supposed to do. So this will be session one. We can talk about what should be done better. For example Rust seems to abhor global variables so if a function needs to modify global type variables then they must(?) be transferred by a mutable reference. So the first change to this code may be to put globals into a structure and just pass a mutable reference to the structure.

In the next session I will break what we already have up into files/modules known in Rust as crates. Therefore Cargo is necessary if you want to work with crates.

Here is the first sessions code:

Code: Select all

fn main() {
  let command = 1u; // command is not mutable and is unsigned int
  let analyze = 2u;
  let compute = 3u;
  let mut run = true; // run is mutable and is boolean 
  let mut computer = command;
  let mut function = 0u;
  let mut iteration = 0u;
  initializef(&mut function, &mut computer); I like capitalized functions, not Rust
  while run {
    if computer == compute {computef(&mut function, &mut computer);}
    if computer == analyze {analyzef(&mut function, &mut computer);}
    if computer == command {commandf(&mut function, &mut computer, &mut run);}
    iteration += 1;
    println!("This is while iteration {}", iteration);
  }
  println!("End of program");
}

fn initializef(f: &mut uint, c: &mut uint) {
  println!("function is Initialize {} computer = {}", *f, *c);
  *f = 1u;
  *c = 2u;
}

fn commandf(f: &mut uint, c: &mut uint, r: &mut bool) {
  println!("function is Command {} computer = {}", *f, *c);
  *r = false;
}

fn analyzef (f: &mut uint, c: &mut uint) {
  println!("function is Analyze {} computer = {}", *f, *c);
  *f = 2u;
  *c = 3u;
}

fn computef (f: &mut uint, c: &mut uint) {
  println!("function is Compute {} computer = {}", *f, *c);
  *f = 3u;
  *c = 1u;
}
Is this interesting enough to proceed? Let me know what you think.
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
zullil
Posts: 6442
Joined: Tue Jan 09, 2007 12:31 am
Location: PA USA
Full name: Louis Zulli

Re: Learning to program in RUST, together

Post by zullil »

Michael Sherwin wrote:For those that want to investigate this new programming language let's begin. I downloaded RUSTC the Rust compiler, Cargo the Rust project manager, the Atom programming editor and a Rust package for atom. Somehow I got it all working.

Rust would seem to have quite a few advantages for chess programming like speed, data safety and maybe simpler SMP with race condition safety. And other advantages. You can research that for yourselves.

The downside (or another upside) to Rust is that it is very strict and so the flexibility of C is lost. If it is an upside then it is because certain mistakes are caught at compile time rather than crash the program at run time.

I have written some sample code that looks like the beginning of a chess program. Well I hope it is anyway. It compiles without warning or errors and does what it is supposed to do. So this will be session one. We can talk about what should be done better. For example Rust seems to abhor global variables so if a function needs to modify global type variables then they must(?) be transferred by a mutable reference. So the first change to this code may be to put globals into a structure and just pass a mutable reference to the structure.

In the next session I will break what we already have up into files/modules known in Rust as crates. Therefore Cargo is necessary if you want to work with crates.

Here is the first sessions code:

Code: Select all

fn main() {
  let command = 1u; // command is not mutable and is unsigned int
  let analyze = 2u;
  let compute = 3u;
  let mut run = true; // run is mutable and is boolean 
  let mut computer = command;
  let mut function = 0u;
  let mut iteration = 0u;
  initializef(&mut function, &mut computer); I like capitalized functions, not Rust
  while run {
    if computer == compute {computef(&mut function, &mut computer);}
    if computer == analyze {analyzef(&mut function, &mut computer);}
    if computer == command {commandf(&mut function, &mut computer, &mut run);}
    iteration += 1;
    println!("This is while iteration {}", iteration);
  }
  println!("End of program");
}

fn initializef(f: &mut uint, c: &mut uint) {
  println!("function is Initialize {} computer = {}", *f, *c);
  *f = 1u;
  *c = 2u;
}

fn commandf(f: &mut uint, c: &mut uint, r: &mut bool) {
  println!("function is Command {} computer = {}", *f, *c);
  *r = false;
}

fn analyzef (f: &mut uint, c: &mut uint) {
  println!("function is Analyze {} computer = {}", *f, *c);
  *f = 2u;
  *c = 3u;
}

fn computef (f: &mut uint, c: &mut uint) {
  println!("function is Compute {} computer = {}", *f, *c);
  *f = 3u;
  *c = 1u;
}
Is this interesting enough to proceed? Let me know what you think.
Have you looked at Go? It seems to offer some of the same features. I seem to recall Don Dailey expressing interest in Go for chess programming.
User avatar
velmarin
Posts: 1600
Joined: Mon Feb 21, 2011 9:48 am

Re: Learning to program in RUST, together

Post by velmarin »

Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Learning to program in RUST, together

Post by Michael Sherwin »

I looked at Go and I would rather just use C. Rust though seems like it might be a language that can replace C, at least for me.

Also in benchmarks that I have seen Rust runs faster than Go. In some benchmarks Rust runs faster than C.
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Learning to program in RUST, together

Post by Michael Sherwin »

Hmm, well, okay I guess that makes this topic too little too late.
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
vincent
Posts: 33
Joined: Tue Jan 19, 2010 8:38 am
Location: Brittany, France

Re: Learning to program in RUST, together

Post by vincent »

Michael Sherwin wrote:
Hmm, well, okay I guess that makes this topic too little too late.
On the contrary, this is the perfect time!

It's funny, I also started to write a chess engine[1] in Rust a few days ago! I was benchmarking Go and Rust (two languages with a lot of hype) against C with a naive prime number algorithm and found out that Rust was a little faster than C on my laptop with this specific code! So I naturally thought that I could try to write another engine[2] from scratch with it (and with bitboard instead of 0x88 this time).

So far I'm reading about magic bitboard move generation while playing with Rust and the language is very interesting and pleasant to use. The commands "cargo test" and "cargo bench" to run unit tests and micro benchmarks without third party libraries seem perfect for what we do.

But Rust is not 1.0 yet, it's still rapidly evolving (it's recommended to use the nightly build of the compiler for instance) but that's a good opportunity to also learn about language design and implementation.

1: https://github.com/vinc/littlewing
2: https://github.com/vinc/purplehaze
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Learning to program in RUST, together

Post by Michael Sherwin »

The "code by example" pages give examples for one type of scope situation and when I try to use basically the same syntax for another scope situation it wont work. And in other situations it seems logical that the same syntax should work-- it doesn't. So I had to look for examples of similar design and/or features and then deduce the syntax by combining ideas. So to get this up and running without warnings or errors I went around the mary_go_round a few dozen times. Very frustrating and time consuming.

A couple examples gave me the idea that structures could be accessed globally with out passing an address. I could not get that to work. Also the syntax using pointers is different from C. I tried putting the structures into a module definition in the same file but that complicated matters. I'll leave that for next time.

Anyway this is doing what it is designed to do. However, if anyone thinks that I am missing the mark in design or language features please feel free to suggest alternatives.

Code: Select all

struct G {
  command:  uint,
  analyze:  uint,
  compute:  uint,
  run:      bool,
  computer: uint,
  function: uint,
}

fn main() {
  let mut g: G = G { // if structure G is in a module the syntax is way different
    command:  1,
    analyze:  2,
    compute:  3,
    run:      true,
    computer: 1,
    function: 0
  };
  let mut iteration = 0u;
  initializef(&mut g);
  while g.run {
    if g.computer == g.compute {computef(&mut g);}
    if g.computer == g.analyze {analyzef(&mut g);}
    if g.computer == g.command {commandf(&mut g);}
    iteration += 1;
    println!("This was while iteration {}", iteration);
  }
  println!("End of program");
}

fn initializef(g: &mut G) {
  println!("function is Initialize {} computer = {}", g.function, g.computer);
  g.function = 1;
  g.computer = g.analyze;
}

fn commandf(g: &mut G) {
  println!("function is Command {} computer = {}", g.function, g.computer);
  g.run = false;
}

fn analyzef (g: &mut G) {
  println!("function is Analyze {} computer = {}", g.function, g.computer);
  g.function = 2;
  g.computer = g.compute;
}

fn computef (g: &mut G) {
  println!("function is Compute {} computer = {}", g.function, g.computer);
  g.function = 3;
  g.computer = g.command;
}
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Learning to program in RUST, together

Post by Michael Sherwin »

I'm up early working on this. Discovered the static keyword for creating global constants. I put them in a module definition and because of that I have to access them using the module name, like m::COMPUTE. Now I read that an external crate does not have to contain a module. So the next order of business will be to create an external crate/file and see if I need a module definition or not. Here is the code as it stands now.

note: Everything in a module including the module itself is private by default. That is why all those pub's are needed.

Code: Select all

pub mod m {
  pub static COMMAND: uint = 1;
  pub static ANALYZE: uint = 2;
  pub static COMPUTE: uint = 3;
  pub static PONDER:  uint = 4;

  #[allow(missing_copy_implementations)]
  pub struct G {
    pub run:      bool,
    pub computer: uint,
    pub function: uint,
  }
}

fn main() {
  let mut g = m::G {
    run:      true,
    computer: 1,
    function: 0
  };
  let mut iteration = 0u;
  initializef(&mut g);
  while g.run {
    if g.computer == m::COMPUTE {computef(&mut g);}
    if g.computer == m::ANALYZE {analyzef(&mut g);}
    if g.computer == m::PONDER  {ponderf (&mut g);}
    if g.computer == m::COMMAND {commandf(&mut g);}
    iteration += 1;
    println!("This was while iteration {}", iteration);
  }
  println!("End of program");
}

fn initializef(g: &mut m::G) {
  println!("function is Initialize {} computer = {}", g.function, g.computer);
  g.function = 1;
  g.computer = m::ANALYZE;
}

fn ponderf(g: &mut m::G) {
  println!("function is Ponder {} computer = {}", g.function, g.computer);
  g.function = 4;
  g.computer = m::COMMAND;
}

fn commandf(g: &mut m::G) {
  println!("function is Command {} computer = {}", g.function, g.computer);
  g.run = false;
}

fn analyzef (g: &mut m::G) {
  println!("function is Analyze {} computer = {}", g.function, g.computer);
  g.function = 2;
  g.computer = m::COMPUTE;
}

fn computef (g: &mut m::G) {
  println!("function is Compute {} computer = {}", g.function, g.computer);
  g.function = 3;
  g.computer = m::PONDER;
}
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Learning to program in RUST, together

Post by Michael Sherwin »

I tried to put the module definition into a file, put the file in the right directory format and run 'cargo new mycrate'. Cargo never saw mycrate. I have no clue what I am doing wrong. I guess I'm done for now until I can get this figured out. Maybe if I can find some better examples.
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Learning to program in RUST, together

Post by Michael Sherwin »

I deleted the project and rebuilt it in the order that an example did it. It seems like a strange order. First I built the library crate that ends up with the name of my program. Like this:

cd c:\
cargo new SkyNet

That creates a SkyNet directory with a src directory under it that contains the file lib.rs. Then I put the module definition into that file. And built like this:

cd SkyNet
cargo build

The crate was built and placed in the target directory.
Then I created the main.rs file and placed it in the src directory. And built it.

cargo build

It built SkyNet.exe and put it in the target directory.

c:\SkyNet\src\lib.rs

Code: Select all

pub mod m {
  pub static COMMAND: uint = 1;
  pub static ANALYZE: uint = 2;
  pub static COMPUTE: uint = 3;
  pub static PONDER:  uint = 4;

  #[allow(missing_copy_implementations)]
  pub struct G {
    pub run:      bool,
    pub computer: uint,
    pub function: uint,
  }
} 

Notice that now the crate name has to be used also and is case sensitive.

c:\SkyNet\src\main.rs

Code: Select all

extern crate SkyNet;

fn main() {
  let mut g = SkyNet::m::G {
    run:      true,
    computer: 1,
    function: 0
  };
  let mut iteration = 0u;
  initializef(&mut g);
  while g.run {
    if g.computer == SkyNet::m::COMPUTE {computef(&mut g);}
    if g.computer == SkyNet::m::ANALYZE {analyzef(&mut g);}
    if g.computer == SkyNet::m::PONDER  {ponderf (&mut g);}
    if g.computer == SkyNet::m::COMMAND {commandf(&mut g);}
    iteration += 1;
    println!("This was while iteration {}", iteration);
  }
  println!("End of program");
}

fn initializef(g: &mut SkyNet::m::G) {
  println!("function is Initialize {} computer = {}", g.function, g.computer);
  g.function = 1;
  g.computer = SkyNet::m::ANALYZE;
}

fn ponderf(g: &mut SkyNet::m::G) {
  println!("function is Ponder {} computer = {}", g.function, g.computer);
  g.function = 4;
  g.computer = SkyNet::m::COMMAND;
}

fn commandf(g: &mut SkyNet::m::G) {
  println!("function is Command {} computer = {}", g.function, g.computer);
  g.run = false;
}

fn analyzef (g: &mut SkyNet::m::G) {
  println!("function is Analyze {} computer = {}", g.function, g.computer);
  g.function = 2;
  g.computer = SkyNet::m::COMPUTE;
}

fn computef (g: &mut SkyNet::m::G) {
  println!("function is Compute {} computer = {}", g.function, g.computer);
  g.function = 3;
  g.computer = SkyNet::m::PONDER;
}
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through