Hacker News new | comments | ask | show | jobs | submit login

Here's an implementation that is equivalent to the modern C++ example (playground link: https://play.rust-lang.org/?version=stable&mode=release&edit...):

  use std::time::SystemTime;

  fn main() -> Result<(), Box<dyn std::error::Error>> {
      let t0 = SystemTime::now();

      let triples = (1..).flat_map(|z|
          (1..=z).flat_map(move |x| 
              (x..=z).filter_map(move |y|
                  if x * x + y * y == z * z {
                      Some((x, y, z))
                  } else {
                      None
                  }
              )
          )
      );
    
      for triple in triples.take(100) {
          println!("{:?}", triple);
      }
    
      let elapsed = t0.elapsed()?;
    
      println!(
          "{}", 
          elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
      );
    
      Ok(())
  }
It takes about .376s to compile in debug mode, about 0.491s in release mode. This was after warming caches; the first run took about 2.071s, of which a large portion was probably loading the compiler and standard library.

In debug mode, it runs in 0.047586s, in release mode, 0.002304.

I was pleasantly surprised to see this is actually better on the build times and debug build performance, given that those are two often cited sore points in Rust.

I would also say that while this is a little bit noisy, it is more readable than the proposed C++20 version. "1.." looks more like a range starting at 1 than "iota(1)" does. There's an actual "if" statement in there.

In fact, while Rust doesn't officially have generator/coroutine support yet, it is available in nightly builds for the implementation of async/await. If you use the nightly compiler, enable the unstable features, and wrap an adapter type around Generator that implements Iterator, you can write:

    let triples = IterGen(||
        for z in 1.. {
            for x in 1..=z {
                for y in x..=z {
                    if x*x + y*y == z*z {
                        yield (x, y, z)
                    }
                }
            }
        }
    );
It's expected that at some point in the coming year or so async/await, and probably the underlying Generator feature, will be stabilized, and I presume the standard library will implement the Iterator trait for appropriate types of Generators (though there is some bikeshedding about the details of that).

Rust doesn't have generators yet, so this is only really fair to compare to the generator/co_yield example in C++ (which is also proposed but not yet standardized). I'd say Rust's syntax compares favorably to that example; the ranges are more clear than the traditional C-style "for" loops, there's native tuple syntax, and it's just be "yield" instead of "co_yield".




Rust sore points regarding compile times have to do with lack of support for binary libraries.

While on C++ I can take advantage of incremental compilation and linking, while using binary libraries for all dependencies, with cargo I have always to build the whole world from scratch minus standard library.


I'm not sure when the last time you've used Rust is, but that hasn't been true in quite a while (not sure how long exactly). Cargo now has incremental compilation, and it's turned on by default. It's great!


I dabble on Rust regularly, usually during plane or train trips.

It still doesn't do incremental linking, and cargo still builds everything from scratch without any support for binary libraries.


Binary libraries don't help so much -- many libraries use generic types and functions (those are instantiated and compiled for each specific instance) which can only be delivered as library "metadata", not codegen'ed, and the latter is the very slow part.


Wrong since C++11 introduced external templates for common instatiation types.

Additionally, it is not like every C++ library is full of meta-programming templates.

Finally, there are other languages with library "metadata" and generic data types, which can easily beat Rust compile times like Delphi, Eiffel and Ada.


Delphi and Eiffel compilers don't do anywhere near the same level of optimization as LLVM does.

And are you sure GCC's Ada has better compile times? My sense is that so few people use Ada at scale that we don't really know.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: