[HN Gopher] From Julia to Rust (2021)
       ___________________________________________________________________
        
       From Julia to Rust (2021)
        
       Author : fanf2
       Score  : 87 points
       Date   : 2024-08-29 14:42 UTC (8 hours ago)
        
 (HTM) web link (miguelraz.github.io)
 (TXT) w3m dump (miguelraz.github.io)
        
       | tiffanyh wrote:
       | Maybe the worst TLDR ever :)
       | 
       | Interesting post, even though I don't understand "Why Rust"
       | because all the reasons cited are not an issue with Julia (eg
       | memory safety).
       | 
       | This seems to not be about Julia at all. It just a post of a
       | person who only knew Julia, and is now wanting to learn another
       | language (which happens to be Rust)
        
         | samatman wrote:
         | That stood out to me as well. The collection of reasons given
         | to prefer Rust to C happens to be completely compatible with
         | preferring Julia to C as well.
         | 
         | There's a different collection of reasons which wouldn't have
         | that property (smol binary, suitable for realtime and embedded,
         | etc), but it isn't the ones the author picked.
        
           | miguelraz wrote:
           | Author here!
           | 
           | Precisely, the most natural symbiosis for a Julia + Rust
           | combo seems to fill a hard-realtime, critical safety or
           | embedded niche with offline simulation.
           | 
           | The Py03 and maturin story is something that we haven't
           | brought to Julia yet and I'd love to have some time to work
           | on a tighter integration story there. For example, getting a
           | hot-reload with Revise.jl and a bindings generator that
           | watches file changes and recompiles and the fly so that a
           | Julia REPL gets updated with the new definitions would be so
           | enviable.
           | 
           | I haven't spoken to Tim Holy to see how to string that
           | together but many of the pieces are there.
        
         | ssivark wrote:
         | I don't think it's a case for switching from one to the other.
         | It seems like an intro to rust from someone whose first
         | language was Julia (which is used as the perspective to
         | contrast with).
        
         | nurettin wrote:
         | Wow I thought it was only me. "Why did you switch?" shouldn't
         | be answered by "this talk, that person's opinion and that
         | powerpoint presentation"
        
           | affinepplan wrote:
           | I don't think this is an article about switching. The author
           | still uses Julia --- he has just learned Rust as well! This
           | is an article about the learning experience and some notable
           | differences and takeaways from the adventure into Rust.
        
             | miguelraz wrote:
             | Right, back then there weren't as many Rust-inclined people
             | in the Julia community and I felt like writing a trip
             | report for my Julia friends.
             | 
             | Now I've done a "From Julia to Rust" workshop at the latest
             | JuliaCon and an accompanying survival guide, so that still
             | ongoing work.
        
           | ayhanfuat wrote:
           | This is not about switching. He mentions his first language
           | was Julia and he became interested in learning Rust. He
           | answers that question and there is nothing wrong with someone
           | getting interested in something by watching talks and getting
           | inspired by people's opinions.
        
             | miguelraz wrote:
             | Yup, this was exactly my reasoning.
        
             | nurettin wrote:
             | I get inspired by things on their own merits and
             | properties. So getting inspired by others sounds like a
             | bunch of romantic LinkedIn grifter BS. Sorry.
        
         | acomjean wrote:
         | There is a good list of Rust learning resources though...
         | 
         | I'll agree that it's mostly about its like using Rust compared
         | to Julia. It's not very dismissive of Julia. The first
         | paragraph lets you know what your in for.
        
         | SkiFire13 wrote:
         | > are not an issue with Julia (eg memory safety)
         | 
         | Note that Julia does allow memory unsafety, for example you can
         | mark array accesses with `@inbounds` to remove bound checks,
         | kinda like how you can use `unsafe` in Rust except it looks
         | much less scary.
         | 
         | It also doesn't help that the official example for how to use
         | it safe was actually not safe [1]. Granted, this is just a
         | single example and has been fixed since then, but it doesn't
         | give a nice impression of their mindset when dealing with
         | memory safety.
         | 
         | More in general there doesn't seem to be a strong mindset for
         | correctness either. See [2] for a collection of such issues.
         | 
         | [1]: https://github.com/JuliaLang/julia/issues/39367
         | 
         | [2]: https://yuri.is/not-julia/
        
       | dist1ll wrote:
       | > For loops are not idiomatic in Rust
       | 
       | That's not really the case. For loops are certainly less common
       | compared to C, but they are completely fine to use. Forcing every
       | loop into an iterator-chain style can sometimes be _more_
       | confusing.
       | 
       | Not to mention doing for-iterations with early exits. Yes, you
       | can use try_fold, but if I'm not writing generic iterator library
       | code, I'd prefer explicit for in cases like this.
       | 
       | > writing Fortran-ey code instead of iterators will lead to pain
       | and slower loops.
       | 
       | No it won't. At least not in the general case. Not to mention
       | that iterators also have performance footguns that are pretty
       | easy to trigger.
        
         | John23832 wrote:
         | >That's not really the case. For loops are certainly less
         | common compared to C, but they are completely fine to use.
         | Forcing every loop into an iterator-chain style can quickly
         | become an unreadable mess.
         | 
         | There are no C style "for" loops in Rust: https://doc.rust-
         | lang.org/reference/expressions/loop-expr.ht...
         | 
         | There is the "for" expression, but that does not give you a
         | C-style "for" loop. It gives you something akin to a "foreach"
         | you might see in Java, C#, Go, etc.
        
           | steveklabnik wrote:
           | From the link:
           | 
           | > A for expression extracts values from an iterator, looping
           | until the iterator is empty.
           | 
           | They look like this:                 for i in 1..10 {
           | println!("{i}");       }
           | 
           | And they're totally fine to use in Rust, I agree that the
           | article is not exactly accurate here.
           | 
           | EDIT: Okay you edited your comment to say this doesn't count.
           | Sure. This is what the author of the post was talking about,
           | though.
        
             | John23832 wrote:
             | I guess the statement
             | 
             | >>That's not really the case. For loops are certainly less
             | common compared to C, but they are completely fine to use.
             | Forcing every loop into an iterator-chain style can quickly
             | become an unreadable mess.
             | 
             | Implies a C-style for loop, some sort of counting
             | accumulator, and an update expression. That doesn't exist
             | in rust. That's all I was saying.
             | 
             | I know who you are, so I know I'm preaching to the
             | preacher.
        
               | steveklabnik wrote:
               | Gotcha. I don't think it implies a C-style for loop,
               | guess we just read things differently :)
        
             | bee_rider wrote:
             | The author of the post says:
             | 
             | > For loops are not idiomatic in Rust - writing Fortran-ey
             | code instead of iterators will lead to pain and slower
             | loops. Spending time reading the examples in the iterator
             | docs and the community solutions in the exercisms will help
             | a lot.
             | 
             | I think they are talking about C style for loops or Fortran
             | style do loops, they explicitly contrast against iterators.
             | 
             | Edit: Although, I wonder, what does an iterator like you've
             | shown compile down to? I'd imagine Rust is smart/modern
             | enough and that iterator is common enough that the assembly
             | emitted looks a lot like a c for loop. Or better.
        
               | steveklabnik wrote:
               | I understood them to be saying that they would prefer
               | (0..10).iter().for_each(|x| println!("{x}"))
               | 
               | over the thing that I wrote.
               | 
               | Many folks do not think of Rust's for loops as using
               | iterators under the hood, and so will often talk about
               | them as though they don't use iterators, even though they
               | technically do.
        
               | miguelraz wrote:
               | Author here, long time no see Steve!
               | 
               | When I wrote this, my main takeaways were numerical
               | computations with arrays, which don't tend to use for
               | loops in Rust, and which require grokking iterators for
               | maximum performance and rayon-parallelism boons.
               | 
               | To a Julia audience, seeing this style of iterator
               | chaining is quite a new flavor to think about composing
               | computation, so I wanted it was with that audience in
               | mind that I wrote this.
        
               | steveklabnik wrote:
               | Hey hey!
               | 
               | Yeah I think that makes sense! I don't do that kind of
               | work and so it's more usual in the kinds of code I write.
        
               | dist1ll wrote:
               | IIRC for loops compile down to a while loop with the same
               | body, that drives the given iterator with .next(), until
               | it returns None.
               | 
               | Since the .next() implementation of std::ops::Range is
               | essentially an i++, you'll quickly arrive at a similar
               | representation as classic C for-loop.
        
               | tialaramex wrote:
               | Rust only "really" has one loop, the one named loop. Loop
               | is an infinite loop that you can break out of (using the
               | break keyword of course).
               | 
               | All the other syntax, including both "for" and "while"
               | loops and the related but technically different "while
               | let" loop, while useful to humans to communicate intent,
               | aren't semantically different - and so they're
               | transformed early in compilation, they are just "syntax
               | sugar" and are de-sugared into rather elaborate loops
               | with their exit condition now a loop break condition etc.
               | 
               | But yes, as in C++ and similar languages, the iterators
               | generate the same machine code as you'd have gotten for
               | writing the C-style for loop from the 1970s, it's just
               | that in Rust you literally can't write that loop.
        
               | bee_rider wrote:
               | Now I've become confused as to what it means for a
               | language to have a thing.
               | 
               | Hypothetically if you do
               | 
               | for i in 1..10 {                     println!("{i}");
               | }
               | 
               | (From earlier) the compiler should have enough
               | information to fully unroll the loop if it feels like it.
               | So it is a different syntax from the programmer's point
               | of view. Maybe it goes through some "this is a loop"
               | stage inside the compiler. But then hypothetically the
               | assembly output could... end up not even having a loop at
               | all (fully unrolled, no jump back, haha).
        
               | steveklabnik wrote:
               | What your parent is saying is that the compiler treats
               | that loop as                 {           let result =
               | match IntoIterator::into_iter(1..10) {               mut
               | iter => loop {                   let next;
               | match iter.next() {                       Some(val) =>
               | next = val,                       None => break,
               | };                   let i = next;                   let
               | () = { println!("{i}"); };               },           };
               | result       }
               | 
               | (95% sure I got that correct)
               | 
               | And so in some sense, "loop" is more primitive than
               | "for".
               | 
               | > But then hypothetically the assembly output could...
               | end up not even having a loop at all
               | 
               | Absolutely, with any of these loops, the compiler may not
               | emit a loop in assembly. And in this case, that seems to
               | be true: https://godbolt.org/z/7Gq69Gvre
        
             | kstrauser wrote:
             | That's nearly identical to Python's approach, too. It
             | doesn't have C-style loops, just ones that consumer
             | iterators.                 for i in range(10):
             | print(i)
             | 
             | consumes 1 value at a time from the `range(10)` generator.
             | `for` has no special knowledge of numbers or ranges or any
             | of that.
        
           | dist1ll wrote:
           | I think that's bit too pedantic. Most people in the Rust
           | community refer to for expressions as for loops (including
           | the book).
           | 
           | It's especially odd to point out this language detail,
           | because for expressions always return the unit type. So it's
           | not like you can do something with the return value (unlike
           | loop expression, which can evaluate to one of its break
           | expressions).
        
             | John23832 wrote:
             | The ergonomics of c style for loops and iterator style
             | loops are totally different.
             | 
             | It's the reason for crates like itertools.
             | 
             | I don't think that is pedantic at all.
        
       | exo-cortex wrote:
       | Just one thing (maybe the author reads this):
       | 
       | The nicest way to avoid the "oh a lot of boilerplate!"-problem
       | with implementing "Add" for a custom type is by using the
       | "derive-more"-crate. Then you simply put a "#[derive(Add)" above
       | your struct. That was the initial reason I switched to Rust
       | myself: because I was writing a dynamical systems solver in C++
       | and had to overload arithmetic operators for my state-struct. But
       | doing this was so complicated and I never felt sure of it
       | performance wise (what if one side is a reference? And so on).
       | 
       | In rust I have a macro and don't have to ever worry about that
       | again.
        
         | miguelraz wrote:
         | Author here!
         | 
         | Oh, that's a neat crate, I'll check it out.
         | 
         | I'd be interested to see if you have benchmarks of your
         | dynamical systems solver in Rust vs the ones implemented in
         | Julia. They've done great work!
        
           | DerSaidin wrote:
           | > Linear Algebra and numerics where not a primary focus of
           | Rust when starting out as they were with Julia.
           | 
           | Typo: where -> were
        
             | miguelraz wrote:
             | Thanks! Fixed.
        
       | miguelraz wrote:
       | Author here!
       | 
       | I have no idea why this blog is making the rounds again and I've
       | learned a lot of Rust since, see my (badly benchmarked!)
       | presentation at this year's Scientific Computing in Rust 2024:
       | 
       | https://www.youtube.com/watch?v=bdsBhqKOe7A
       | 
       | and a PR I sent in for the Rust compiler to speed it up for some
       | low hanging fruit:
       | 
       | https://github.com/rust-lang/rust/pull/110477
       | 
       | I'll have to revisit this blog at some point and see what I
       | should update, as well as a "From Rust to Julia" post for those
       | that want to venture into that world as well.
        
         | solarengineer wrote:
         | You could edit your blog post to say what you've just said
        
         | doodpants wrote:
         | Peeve of mine: blog posts that lack a date stamp. The only date
         | appearing anywhere in the article is at the bottom, where it
         | says "Last modified: August 29, 2024." So for all I knew it was
         | a brand new post, until this comment. How old is it actually?
        
       | Decabytes wrote:
       | I'm still not understanding the switch to Rust other than for
       | education (which is fine). All of the things you get from Rust
       | with memory safety you get in Julia with the Garbage Collector?
        
         | miguelraz wrote:
         | I didn't switch!
         | 
         | At least for some scientific computing codes, but I did learn a
         | lot of Rust along the way and extended my knowledge into (some)
         | embedded and systems programming. Learning has been fun and the
         | Rust people have been very friendly.
        
       | nritchie wrote:
       | I'm a physicist whose written substantial projects in both Julia
       | and Rust (and C/C++/Object Pascal/Java/Python/...). I'm also a
       | person who refactors frequently. While my mind was initially
       | blown away by all the cleverness in Julia, I eventually found
       | that for non-trivial packages the "time-to-first-X" became
       | painful - way more painful than compiling Rust code (mostly with
       | debug occasionally with --release). Plus the amazing generality
       | of Julia code was both a blessing and a curse. Julia really needs
       | interfaces to ensure that a duck really is a duck. In the end, I
       | find Rust (despite/maybe because of) the picky compiler to be
       | overall much more productive. With Rust, I find I can make major
       | refactors, when the code compiles and my test code runs, I'm good
       | to go. With Julia, months after I've refactored, I'm still
       | finding footguns. I still use both but it is Rust that has my
       | heart these days.
       | 
       | Other thoughts: Developing Rust on Windows is painful but on
       | Linux a joy. both cargo and Julia package managers are wonderful
       | compared to other language alternatives.
        
         | miguelraz wrote:
         | I'll agree on several counts (as a physicist too!):
         | 
         | * Rust's tooling lets you have a base-floor of what is
         | acceptable code that is much more palatable than non-top tier
         | Julia codes. There's a _world_ of difference opening a random
         | crate 's code in Rust that has been linted/clippy'd/check'd by
         | the compiler rather than a random Julia package that a
         | coworker/colleague just fired up. This tooling is getting
         | better and better in Julia and I'd be interested to hear which
         | Julia projects you worked on were really hampered by TTFX and
         | refactoring woes. Hard agree on the footguns - I want the
         | VSCode plugin to be better at detecting dead code, it cost me
         | weeks on a project lately.
         | 
         | * I'm also excited for some notion of interfaces to come to
         | Julia. Perhaps it will be a 2.0 thing, but there's still lots
         | of design stuff to figure out.
         | 
         | * We have different understandings of "productive" for
         | different focii then - I still find it painful to do the
         | equivalent of `rand(1:10, (20, 20))` in Rust and I can get STEM
         | people to be productive with Julia before you can even
         | finishing saying "borrowchecker".
        
         | yrlin wrote:
         | > ... I eventually found that for non-trivial packages the
         | "time-to-first-X" became painful ...
         | 
         | Have you checked the TTFX in 1.9+? It is significantly reduced
         | for various packages e.g. Plots.jl.
        
       | a-dub wrote:
       | interesting question: does it still make sense to have different
       | or specialized languages for scientific computing vs generalized
       | software engineering?
        
         | miguelraz wrote:
         | No clue! We'll see how they play out in time I guess.
        
       ___________________________________________________________________
       (page generated 2024-08-29 23:02 UTC)