Re:Falling in love with Rust
by gamegoblin on Tuesday September 18, 2018 @11:13PM
(#18021390)
It's idiomatically done with newline separators, e.g:
let sum = vec_of_ints
.iter()
.filter(|x| x > 5)
.map(|x| x.pow(2))
.take(3)
.sum()
That is, iterate my vec, only consider values > 5, square them, take the first 3, them sum them.Consider the imperative code:
let mut sum = 0;
let mut n = 0;
for x in vec_of_ints {
if x > 5 {
sum += x.pow(2);
n += 1;
if n == 3 {
break;
}
}
}
I think the chained combinator approach is much easier to see exactly what's happening (and is often higher performance!)That's nice and all. But then you have abominations like this:
state
.db
.send(Queries::GetTopTenHottestYears)
.from_err()
.and_then(move |res| {
result.push(res.unwrap());
state
.db
.send(Queries::GetTopTenColdestYears)
.from_err()
.and_then(move |res| {
result.push(res.unwrap());
state
.db
.send(Queries::GetTopTenHottestMonths)
.from_err()
.and_then(move |res| {
result.push(res.unwrap());
state
.db
.send(Queries::GetTopTenColdestMonths)
.from_err()
.and_then(move |res| {
result.push(res.unwrap());
fut_ok(result)
})
})
})
})
.and_then(|res| Ok(HttpResponse::Ok().json(res)))
.responder()
https://github.com/actix/examples/blob/master/async_db/src/m...My suspicion is the people do this to avoid "variable does not live long enough" type errors.
Re:Falling in love with Rust
by gamegoblin on Wednesday September 19, 2018 @03:36AM
(#18022473)
I believe that is written that way because it's using futures. Once async/await lands this year, all of the futures combinator madness goes away.
The code could use closures to split the expression or define local functions on the bottom of the surrounding function (a.k.a Haskell style). This would increase readability a lot.
Example: https://play.rust-lang.org/?gist=7ea1a39971399d0429f0369cb9e...
This is called the 'pyramid of doom' in the nodejs circles
Well, dunno, in my opinion both are equally obscure. I personally don't like "dot notation" and that's one of the reason I don't like Rust.
The main problem I see with dot notation is the Pigeon hole problem: why sometimes you write x(y) and sometimes y.x()? While the functions in the above example are trivial, there exist not so obvious cases.
Doesn't the chained version still iterate over all the elements and squares them before taking the first 3 bigger than 5? the second version only goes over the minimum necessary elements and then breaks. How can the first be higher performance?
Re:Falling in love with Rust
by gamegoblin on Wednesday September 19, 2018 @05:06PM
(#18027712)
No, the iterators are "lazy" (pull-based). Both implementations will perform the same amount of work.
Oftentimes the iterator will be faster, though, because the compiler can reason about what you're doing easier with an iterator vs. iterating via manual sequential indexing.
Re:Falling in love with Rust
by staticassertion on Tuesday September 18, 2018 @09:38PM
(#18020963)
It's often idiomatic. I've never found it to be indecipherable at all. I actually find it to be quite readable in most contexts where intermediate variables are just noise.
Iterators are a typical example of this.
vec![0, 1, 2, 3].into_iter() .filter(|x| x % 2 == 0) // Keep the evens .map(|y| y + 1 ) // Add 1 to elements .rev(); // Reverse the iterator
Adding intermediates would just add noise for code like this.
Re:Falling in love with Rust
by smittywerben on Tuesday September 18, 2018 @11:40PM
(#18021510)
It helps me with autocomplete. In Python at least, I find
int.__add__(a, b)
is less idiomatic than a.add(b)
which removes the global abstract. Though I see it looks less symmetric.I'm not a Rustacean - I only speak to the syntax difference.
Is this idiomatic? It seems powerfully indecipherable/illegible