How much syntax sugar has Rust?


#1

Rust is a low-level programming language, so I wonder what these beautiful abstractions transform to.

I’ve a few idea about how could this be like, e.g. a for loop going to be an if and goto etc. How about the other ones?


#2

A few quick things I can recall just right now (in pairs of sugared and desugared things):

fn func<F>() where F: Fn(u32) -> u64 {} // is the same as:
fn func<F>() where F: Fn<(u32,), Output=u64> {}
let a = [1u32, 2, 3, 4];

let b = &a[..];
let c = &a[1..];
let d = &a[..3];
let e = &a[1..3];

// are the same as:

let b = &a[RangeFull];
let c = &a[RangeFrom {start: 1}];
let d = &a[RangeTo {end: 1}];
let e = &a[Range {start: 1, end: 3}];

#3

Is ‘end: 1’ right?


#4

See yourself: http://doc.rust-lang.org/nightly/std/ops/struct.RangeTo.html.


#5

Closures are entirely sugar.


#6

And indexing is also desugars further:

// from: 
let x = &a[1..3];
// to:
let x = &a.index(Range { start: 1, end: 3 });

#7

Then if let and while let can be viewed as a sugar for match { ... } and loop { match { ... } }.


#8

I wonder if match is a sugar.


#9

No, you can’t do pattern matching without match, it’s a basic language feature.


#10

Many binary operations are implemented with traits (see Add, Sub, Div, Mul for example), so you also think of them as a syntax sugar, although I’m not sure if it’s a real sugar or just an implementations detail of operator overloading.


#11

Deref coercion is some nice sugar.

let s: String = "hi".to_string();
let t: &str = &s;

And traits as used for example with Into<Cow<'a, str>> and AsRef<Path> provide very sugary interfaces without extra language features:

File::open("file.txt");  // fn open<P: AsRef<Path>>(path: P)

#12

I’m not sure trait bounds usage can be qualified as a sugar, as it’s more a type system feature.


#13

Also dynamic dispatch with trait objects can be thought as a sugar, as it creates virtual method tables and “fat pointers” behind the scene.


#14

In the end, everything is syntax sugar for some sequence of literal bytes; I mean, where do you draw the line?


#15

without extra explanation, newbie will be get confused.

Things like,

I still can not understand

File::open("file.txt");  // fn open<P: AsRef<Path>>(path: P)

“file.txt” is &str.

but no AsRef impl for it

impl AsRef<Path> for Path
impl AsRef<Path> for OsStr
impl AsRef<Path> for OsString
impl AsRef<Path> for str
impl AsRef<Path> for String
impl AsRef<Path> for PathBuf

can anyone give me some explanation? thanks.


#16

It is actually, but in two steps. You have the impl AsRef<Path> for str implementation for str and impl<'a, T, U> AsRef<U> for &'a T where U: ?Sized, T: AsRef<U> + ?Sized which makes every reference to T implement AsRef<U> if T: AsRef<U>. This makes &str implement AsRef<Path> because str implements it.


#17

I did make a small example of &String turning into &str by itself (by “coercion”)


#18

I mean Deref coercion confuse newbie in general, not meaning your example is confusing. I understand it only after the nightly doc comes out. Thanks for your example.


#19

Thanks. that makes me feel better. I feel bad when I can not reason something.


#20

That’s good. Ask questions :smile: