From two small Rust tutorials

bearophile via Digitalmars-d digitalmars-d at puremagic.com
Sat Aug 16 02:19:51 PDT 2014


Recently I've found two very small introductions to the Rust 
language. Below I list some of the things I've found in them.

The first tutorial is:
http://matej-lach.me/rust-basics/

------------------

The Rust tuple syntax similar to Kenji's:

let (i, result) = (0i, 0i);
let (x, y, z) = (15i, "string", 29.99f64);
let (mut s, a, mut m) = ("can change", "cannot", "can");

------------------

Nice uniform names for the integral values (but uint and int are 
variable length, I don't know if this is a good idea, I don't 
like this much):

>Rust has the following primitive numeric types: u8, i8, u16, 
>i16, u32, i32, u64 and i64 - it also has the aliases int and 
>uint for i64 or i32 and u64 or u32 respectively, (depending on 
>whether the OS is 64 or 32-bit).<

------------------

The switch syntax supports floating point intervals too:

match x {
     1.0..1.99 => println!("x is between one and two"),
     2.0..2.99 => println!("x is between two and three"),
     3.0..3.99 => println!("x is between three and four"),
     4.0..4.99 => println!("x is between four and five"),
     5.0..5.99 => println!("x is between five and six"),
     _ => println!("x is bigger than five") // catches all other 
possible values of `x`
}


That feature can be added to D too, if it's desired:

void main() {
     double x;
     case (x) {
         case 1.0: .. case 1.99: return writeln("x is between one 
and two");
         case 2.0: .. case 2.99: return writeln("x is between two 
and three");
         case 3.0: .. case 3.99: return writeln("x is between 
three and four");
         case 4.0: .. case 4.99: return writeln("x is between four 
and five");
         case 5.0: .. case 5.99: return writeln("x is between five 
and six");
         default:                return writeln("x is bigger than 
five");
}


But what about x = 1.999? That Rust code looks buggy.

This hypotetical D code looks more correct, so it's tricky (I 
used T because the nextDown of a float is different from the 
nextDown of a double/real):

void main() {
     import std.math: nextDown;
     double x;
     alias T = typeof(x);
     case (x) {
         case 1.0: .. case nextDown(T(2)):
             return writeln("x is between one and two");
         case 2.0: .. case nextDown(T(3)):
             return writeln("x is between two and three");
         case 3.0: .. case nextDown(T(4)):
             return writeln("x is between three and four");
         case 4.0: .. case nextDown(T(5)):
             return writeln("x is between four and five");
         case 5.0: .. case nextDown(T(6)):
             return writeln("x is between five and six");
         default:
             return writeln("x is bigger than five");
}

------------------

The second tutorial:
http://pudgepacket.github.io/rust/2014/08/11/taste-of-rust-pt-2/


A little function that converts a string (line) to a vector of 
doubles:

fn extract_line_data<T: std::from_str::FromStr>(line: &str) -> 
Vec<T> {
     line.trim().split(' ').filter_map(|s| 
from_str::<T>(s)).collect()
}


The same function written in a more didactic style:

fn extract_line_data<T: std::from_str::FromStr>(line: &str) -> 
Vec<T> {
     // line = "f 1 2 3 4\n"

     // Remove line endings
     let trimmed = line.trim();
     // trimmed = "f 1 2 3 4"

     // Split on space
     let split = trimmed.split(' ');
     // split = ["f", "1", "2", "3", "4"]

     // Map from_str over the split array
     //   collect all the successfuly converted values into a 
vector
     let converted = split.filter_map(|s| 
from_str::<T>(s)).collect();
     // converted = [1, 2, 3, 4]

     return converted
}


The from_str is related to std.conv.to (but I think it overloads 
the return type, as in the Haskell function, that is not possible 
in D).

When you try to convert the "f" string using from_str it doesn't 
raise an exception like std.conv.to because from_str returns an 
Option<T>, similar to Phobos Nullable!T.

So they have used filter_map to filter away the Null conversions. 
So it's similar to this D code:


T[] extractLineData(T)(in string line) {
     return line
            .split
            .map!(s => s.maybeTo!T)
            .filter!(m => !m.isNull)
            .map!(m => m.get)
            .array;
}


Where maybeTo is similar to std.conv.to but returns a Nullable!T 
(https://d.puremagic.com/issues/show_bug.cgi?id=6840 ).

Probably it's a good idea to add to Phobos some more functions 
(like filterMap) that manage ranges of Nullables in a smarter way 
(this is also quite commonly done in Scala language).

Bye,
bearophile


More information about the Digitalmars-d mailing list