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