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?
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?
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}];
Is 'end: 1
' right?
See yourself: RangeTo in std::ops - Rust.
Closures are entirely sugar.
And indexing is also desugars further:
// from:
let x = &a[1..3];
// to:
let x = &a.index(Range { start: 1, end: 3 });
Then if let
and while let
can be viewed as a sugar for match { ... }
and loop { match { ... } }
.
I wonder if match
is a sugar.
No, you can't do pattern matching without match, it's a basic language feature.
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.
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)
I'm not sure trait bounds usage can be qualified as a sugar, as it's more a type system feature.
Also dynamic dispatch with trait objects can be thought as a sugar, as it creates virtual method tables and "fat pointers" behind the scene.
In the end, everything is syntax sugar for some sequence of literal bytes; I mean, where do you draw the line?
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.
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.
I did make a small example of &String
turning into &str
by itself (by "coercion")
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.
Thanks. that makes me feel better. I feel bad when I can not reason something.
That's good. Ask questions