[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)