5 ms·
Or this: pub fn from_bytes(bytes: &'a [u8]) -> IResult<&'a [u8], C<'a>> { ... } or something like this: fn parse_response<'a>(bytes: &'a [u8]) ->
by lossolo 10y ago
Or this:
pub fn from_bytes(bytes: &'a [u8]) -> IResult<&'a [u8], C<'a>> {
...
}
or something like this:
fn parse_response<'a>(bytes: &'a [u8]) -> IResult<&'a [u8], C<'a>> {
switch!(bytes, tuple!(be_u32, be_u32),
(::CONNECT_ACTION_ID, tid) => map!(be_u64, |cid| B::new(tid, ResponseType::Connect(cid)) ) |
(::ANNOUNCE_IPV4_ACTION_ID, tid) => map!(call!(W::from_bytes_v4), |ann_res| {
C::new(tid, ResponseType::Announce(ann_res))
}) |
- steveklabnik 10y agoYou're missing a <'a> in the declaration there ;) "from_bytes is a public function with one lifetime parameter, a. It takes one argument, a slice of u8 with the lifetime 'a, and returns an IResult, which gives back a slice of u8 with the lifetime 'a in the success case, and some type C, which is also parameterized with the lifetime 'a, in the failure case." This is not really normal rust code; it's nom, which is a very macro-heavy DSL. There are decent upsides, and I love nom, but its downside is that it does look a bit odd.
- nitrogen 10y agoIt would be amazing if there were a parser that would translate Rust declarations into english. I think something like that exists for C, but I can't recall the name or how effective it is.
- steveklabnik 10y agohttp://cdecl.org/ http://cdecl.org/
- Sammi 10y agoIt doesn't look a bit odd. It looks impenetrable.
- steveklabnik 10y agoWell, without all the whitespace, it is ;)
- andrewflnr 10y agoSeriously, you can't strip out the whitespace and then pretend to make reasonable critiques of readability.
- e12e 10y agoIt's a bit ironic that something that uses a lot of macros becomes hard to read. Even the link provided by marquisee in a sibling common seems to have almost a ratio of 2:1 of "signal noise" (or (too) densely coded meta-code) to the amount of "actual" code. Have there been any (recent) discussions on how to make this stuff friendlier? I mean, one could always just bootstrap lisp on top of ecl[1], like clasp[2] does, and either generate rust code, or just machine code -- but even for plain rust it seems it should be possible to this stuff in a friendlier way? I'm wondering if it wouldn't be worth it to have a more verbose syntax and/or keywords for this stuff -- it really does appear to me as a usability barrier -- not just because it's new and strange. Reminds me a bit about perl's use of "sigils" which I never quite thought made a lot of sense personally. I'm firmly in the camp that if you want more syntax than common lisp or smalltalk, you need a really good reason for every bit you add. And while I like a lot of things about rust, I'm starting to wonder if this isn't an area that really needs improving. Kind of like how C++14 tries very hard to get rid of a lot of stuff. [1] "Embeddable Common Lisp" https://common-lisp.net/project/ecl/ https://common-lisp.net/project/ecl/ [2] https://github.com/drmeister/clasp https://github.com/drmeister/clasp
- steveklabnik 10y agoI don't think it's ironic; macros enable new syntax, so you'll see it much less than "regular" Rust code, and so it will look a little strange. What parts of that link do you think are "meta" vs "actual"? It's not like we just added syntax for the fun of it :) "Just embed a Lisp" is very far from a "just", and, most non-lispers find Lisp very hard to read, specifically because there is no syntax.
- e12e 10y agoFair enough, "just embed lisp" was a bit tounge-in-cheek. I suppose what I mean is that lisp macros, while powerful, don't need to add syntax that is jarringly different from other syntax (although they certainly can). I suppose I think that stuff like: fn parse_response<'a>(bytes: &'a [u8]) -> IResult<&'a [u8], TrackerResponse<'a>> { switch!(bytes, tuple!(be_u32, be_u32), (::CONNECT_ACTION_ID, tid) => map!(be_u64, |cid| TrackerResponse::new(tid, ResponseType::Connect(cid)) ) | (...) Appears to be very dense in very terse type and life-time information, compared to the variable names, function calls/macro expansions. I get that it might be necessary at times, I just think it is a worthy goal to strive to make code look somewhat simple, even when doing complex things. Example, in this case, with all the lifetimes(?) being the same(?) 'a, could perhaps the compiler infer that? Would it be more useful to make it explicit when they differ? That kind of thing. [ed: As or it being ironic, I see powerful constructs like macros more as a tool for making complex things simpler, not to complicate simple things. That's what I mean when I say "macro-heavy" code being hard to read is ironic. It could of course be that this example really is complex, but it kind of strikes me as looking more "complected" than "complex".]
- marquisee 10y agoI wouldn't take this as representative of normal Rust code. This is standard nom which I would categorize very much as a DSL of sorts for creating parser combinators. In order to understand this code you really have to understand the fundamentals of nom as the reason it is so powerful is because there is a bit of magic going on here. Also, I knew this piece of code looked familiar. For those that wanted to see this code with whitespace, https://github.com/GGist/bip-rs/blob/master/bip_utracker/src/response.rs#L108-L124 https://github.com/GGist/bip-rs/blob/master/bip_utracker/src....