impl<'a> AnyRefExt<'a> for &'a Header {
#[inline]
fn as_ref<T: 'static>(self) -> Option<&'a T> {
trait UncheckedAnyRefExt<'a> {
unsafe fn as_ref_unchecked<T: 'static>(self) -> &'a T;
}
//I am guessing the second line is special because Rust can't deduce "to" should be a TraitObject type?
let raw = require_single_field!(raw);
let to: TraitObject = transmute_copy(&self);
//is this adding header and 'static together?
pub trait HeaderMarker<OutputType: Header + 'static> {
//I have zero clue what this is doing
//I can't even fathom a guess
match *self {
Past => write!(f.buf, "0"),
ExpiresDate(ref tm) => tm.fmt_header(f),
}
//so _raw is a reference to a vector of bytes inside [] and it might possibly return whatever a box is of headers?
fn parse_header(_raw: &[Vec<u8>]) -> Option<Box<Header>> {
//is there really a language keyword called macro_rules! ?
macro_rules! impl_header_from_fromstr {
//what in the world is ($ty:ty)?
($ty:ty) => (impl Header for $ty {
fn parse_header(raw: &[Vec<u8>]) -> Option<$ty> {
//who thought "h.is::<H>()" was a good way to test a type? Why not "h.is(H)?" Why the => ?
//what is this even returning? a tuple of false and None?
Typed(ref h) if h.is::<H>() => {
(false, None)
},
//... why not UTF-8? Because "{}"?
format_args!(format_but_not_utf8, "{}", HeaderShowAdapter(h))
The names don't make any sense to me at all. What the hell is an AnyRefExt? How does an UncheckedAnyRefExt differ? What in the world is the match thing doing? Why the asterisk on self? Why all the apostrophes and colons and dollar signs and exclamation points? Why is there both -> and =>? How does an &' differ from a '?
I could probably learn the language with a huge time investment. But for something aiming to fill the role of systems programming, it's just so incredibly different from everything else. It almost feels like they are going out of their way to make it as different as possible.
I know, this is all syntax stuff. C++ template meta-programming syntax is pretty insane, too, and took me a while to pick up. Yet when I attempt to read up on the syntax and the reasoning, it becomes even more confusing. I don't expect them to write a C++ clone, I understand this is their own language. But just a tiny modicum of reflection that people have spent 15+ years learning the syntaxes and behaviors of C-like languages would be so greatly appreciated. I mean, you see how Haskell is doing, and a lot of people blame that on the absolutely alien syntax to anything programmers are used to.
Yet, with Rust, everyone else with C-family backgrounds just seem to look at this, and go, "oh yeah that makes sense." Boggles my mind.
Have you written any Java code? There is basically the same thing, except they use & instead of + to build unions of type bounds.
And about all the * and & stuff: That's pointer stuff. It is very similar to how it works in C/C++. I think it's just a bit simpler in Rust (you are required to use & to pass something by reference where in C++ you don't see at the call site if something is passed by value or by reference).
About Box: Terms like "auto boxing" are known from other languages (Java), so this is not a new terminology invented by Rust.
-> for defining the return type of a function is also not an invention of Rust. I don't know many functional languages but Haskell uses it, and C++11 uses it! So coming from C++ you should know that. ;)
Before I begin, let me just say that you have chosen the worst possible piece of Rust code for someone who has never looked at the language before. :P
> I am guessing the second line is special because Rust
> can't deduce "to" should be a TraitObject type?
`transmute` and its kin are stdlib functions used to completely subvert the type system by casting any one type to any other type of the same size in memory. Their use is highly discouraged since they're so easy to misuse. You're correct in that Rust cannot deduce what `to` is supposed to be on this line (because by definition `transmute` is freeform and there is no context to infer the resultant type), hence requiring an explicit type annotation.
> is this adding header and 'static together?
Within trait bounds, `+` allows you to specify multiple bounds for a generic type. So it's not adding, but it's taking the union. :)
> so _raw is a reference to a vector of bytes inside []
> and it might possibly return whatever a box is of
> headers?
`_raw` is a reference to an array of vectors of bytes (in this case, a reference to an array of various binary data which has already been read into byte vectors). `parse_headers` will either return a heap-allocated header (`Box` is just a bog-standard thing allocated on the heap), or, if it fails to parse for whatever reason, it will return a value that clearly indicates that an error occurred.
> is there really a language keyword called macro_rules! ?
Nope, it's just a macro (that just so happens to be used to define other macros).
> who thought "h.is::<H>()" was a good way to test a
> type? Why not "h.is(H)?"
Type parameters are usually inferred, so you don't want them mucking up your actual parameter list. In C++ it would look like `is<H>()`, which is much nicer, except that this requires conflating parsing with type checking (see also http://en.wikipedia.org/wiki/The_lexer_hack). Rust thinks this is gross, so it arbitrarily uses `::` to denote the beginning a type parameter list in that context. It's gross, it sucks, it's literally the worst thing about Rust's syntax and 100% of people you survey will agree with you. But fortunately you rarely need to use it because type inference works so well. But inference can't here because Chris is trying to show off Rust's `Any` type, which is a library type that can be used to emulate dynamic typing, which requires a type switch to actually use the type for anything.
> what is this even returning? a tuple of false and None?
Correct!
> why not UTF-8? Because "{}"?
Beats me, this line is goofy. :) `format_args!` is an implementation detail for string formatting in Rust, it's unheard of to use it directly.
> What the hell is an AnyRefExt?
It's an implementation detail that was copied-and-pasted out of the stdlib specifically to facilitate this code snippet. We typically don't bother to fuss over the identifiers of things that users should never need to worry about. :)
> How does an UncheckedAnyRefExt differ?
You'd have to ask Chris Morgan, Rust has no control over what users name their own types!
> What in the world is the match thing doing?
It's just a beefed-up switch statement, ubiquitous throughout Rust code as it is used for working with enums (tagged unions). See http://doc.rust-lang.org/guide.html#match
> Why the asterisk on self?
The asterisk is the dereference operator, the same as C.
> Why all the apostrophes and colons and dollar signs and
> exclamation points?
Apostrophes: ML-inspired syntax to syntactically distinguish lifetime parameters. You see one, it means you're looking at a lifetime.
Colons: you'll have to be more specific, colons are literally every programming language designer's favorite symbol.
Dollar signs: only ever used while defining macros, which you should rarely ever read and even more rarely use.
Exclamation points: used to denote that you're using a macro and that what looks like a function call is actually going to expand to arbitrary code at compile time.
> Why is there both -> and =>?
`->` is used on functions and denotes the return type of the function. That's all it's used for. `=>` is used within `match`: `foo => bar` in Rust is the same as `case foo: bar` in C. That's all it's used for.
> How does an &' differ from a '?
An apostrophe just indicates a lifetime, which all references have (though they're inferred in the overwhelming majority of cases).
Many of the above things would have been made clear by reading the tutorial (http://doc.rust-lang.org/guide.html). I encourage you to do so if you'd like to learn more! Feel free to also hop onto our IRC channel at irc.mozilla.org to ask any questions at all, even ones that you think are stupid or obvious. :)
Thanks a lot for taking the time to reply! That did help a lot.
> you have chosen the worst possible piece of Rust code for someone who has never looked at the language before
That's my luck :P
I was in the middle of turning my HTTP message library from a series of "setHeaderName(value)" functions into just a single "setHeader(name, value)" and was told it had some innovative ideas on how to handle HTTP headers. And I have no doubt it does ... if I could make any sense of it.
Really glad to hear a lot of the vague names were library-specific, the really evil stuff shouldn't ever be used (though I'd argue it shouldn't be exposed outside of the stdlib if true), you definitely cleared up -> and => beautifully, I think the excess colons are a type annotation (used to 'type name' and not 'name: [type]'), and although I still have some questions (around ' and & specifics), I'll read up on your guide instead. Thanks again!
Have you read the Rust Guide? It starts off with the basic cases where the syntax makes sense. Most of the weird stuff is either macro weirdness or making sure the grammar is simple (e.g., the function::<blah>() business).
> But for something aiming to fill the role of systems programming, it's just so incredibly different from everything else. It almost feels like they are going out of their way to make it as different as possible.
Different compared to: most programming languages? Systems programming languages? Just C/++?
> I mean, you see how Haskell is doing, and a lot of people blame that on the absolutely alien syntax to anything programmers are used to.
Its syntax fits how it operates. Should Haskell have -() at the end of functions, like C-like and ML? No, since Haskell uses partial application and currying - the ()-stuff would likely end up as cruft. A function of three arguments in Haskell is not passing in three values as a tuple: it is a function that takes one argument and returns a function - that function is a function that takes one argument and returns a function... how is that clear when you write it as `f(x,y,z)? Not to mention if you partially apply it.
Can you write Haskell code as a sequence of declarations and expressions? Arguably no, since it has non-strict evaluation; having a list of declarations and expressions would be misleading, since they can really be evaluated in any order.
What can be contested is the significant layout (though it is optional) and user-definable operators. Though I think Haskell code would become really crufty without operators, since they sometimes make expressions more clear than a series of prefix-oriented functions.
I could probably learn the language with a huge time investment. But for something aiming to fill the role of systems programming, it's just so incredibly different from everything else. It almost feels like they are going out of their way to make it as different as possible.
I know, this is all syntax stuff. C++ template meta-programming syntax is pretty insane, too, and took me a while to pick up. Yet when I attempt to read up on the syntax and the reasoning, it becomes even more confusing. I don't expect them to write a C++ clone, I understand this is their own language. But just a tiny modicum of reflection that people have spent 15+ years learning the syntaxes and behaviors of C-like languages would be so greatly appreciated. I mean, you see how Haskell is doing, and a lot of people blame that on the absolutely alien syntax to anything programmers are used to.
Yet, with Rust, everyone else with C-family backgrounds just seem to look at this, and go, "oh yeah that makes sense." Boggles my mind.