5 ms·
> A better catchphrase for Julia might be "The best expressiveness / performance tradeoff you have ever seen". Man, Jakob just has a way of writing that gets r
by blindseer 4y ago
> A better catchphrase for Julia might be "The best expressiveness / performance tradeoff you have ever seen".
Man, Jakob just has a way of writing that gets right to the point. Nice post.
My only complaint about the post is that in Python you have many different REPL options. For example, both ipython and bpython are miles ahead of the Julia REPL. I agree though that the Julia default REPL is better than the Python default REPL. I particularly like the shell mode in Julia. You can also make your own modes, like a sql mode or any custom DSL mode.
I have been very critical about Julia in the past, so I'll say some positive things before I complain more :)
- The package management in Julia is god-like. Specifically, there's a whole subset of packages that are just binaries and libraries cross compiled on VMs for Windows / Mac / Linux + x86 / x64 / ARM, and it just works. There's no more trying to compile code on a users computer when trying to install a package, it's beautiful. It is truly a phenomenal piece of engineering, and I cannot praise it enough. Hats off to the core team responsible for this.
- Multithreading is such a joy to use. Compared to any other dynamic GC language, Julia and Go are pretty much up there in terms of usability + features. So much better than Python or R. But while I prefer Julia over Go, I do prefer Rust over Julia.
Now for some of my grievances. I'm a nobody in the Julia community so take my word for what it is worth.
- Optimizing Julia code is a joy. However, learning how to optimize Julia code not straightforward. If you are coming from Python and/or don't have experience thinking about memory, cache lines, references, mutability etc, you have your work cut out for you in terms of learning how to optimize Julia code. In addition to that, there are Julia specific things you need to learn to know how to optimize your code. Do you know what the function barrier paradigm is? No? Too bad, now your codebase is 10x slower and refactoring could take weeks. And that's just the theory of everything you need to learn. There's SO many subtle ways your Julia code can be slow because the compiler wasn't able to "see through your code". And the tooling here is getting better but still has a LOONNNGGG way to go. Statically being able to check and assert for problematic inferences will improve this for me a la JET.jl but right now JET.jl is too slow to run on a large codebase.
- Thinking with Multiple Dispatch (MD) is much like Thinking with Portals. Once you get it, you have this ah-ha moment. But the type system is overloaded in my opinion. You HAVE to use the type system for MD but people also use it for interfaces (AbstractArray for example). I think adding inheritance in the abstract type system was a mistake, and a trait or interface like approach would be way better for this. Maybe something like concrete types for dispatch and abstract types for interfaces? I don't think this will EVER change though, not in Julia 2.0 or 3.0 or later, because it is SO ingrained into the Julia community. I'm not explaining this well here but I've complained about it before in previous comments on HN and am too lazy to go find it and copy paste :)
- There's a number of minor syntax / usability gripes I have that I don't think will ever be fixed as well. I generally think a programming language should incentivize you to "do the right thing", often my making it easier to type. In Julia this framework of thinking exists but isn't applied consistently. It is easier to create a immutable struct than a mutable struct
struct Immutable
x::Int
y::Int
end
# vs
mutable struct Mutable
x::Int
y::Int
end
However, if you want to use it to store user data, if you choose immutable structs, your interface for users is EXTREMELY annoying. For example, if they want to update `x` from `1` to be `2`.
im = Immutable(1, 3)
im = Immutable(2, im.y)
With mutable structs:
m = Mutable(1, 3)
m.x = 2
There's third party packages that make this easier but this should ABSOLUTELY be in Base.
There's similar complaints I have about type names in Julia. I'm incentivized to write `::String` instead of `::AbstractString`, `::Int` instead of `::Integer`. In Julia using `AbstractString` is almost always preferred.
The naming is also quite annoying. Why does `AbstractString` have `Abstract` in the name but `Integer` not, when both of them are abstract types?
I've said this before and I'll say it again. I think Julia core devs should have a usability expert come in and review their whole codebase and workflows and make suggestions. I have no idea how Rust has nailed this so well. In Rust, so many things are just consistent. You can guess what the names or behavior of what you want so often, it's awesome.
TLDR:
If you are thinking of using Julia for a large production codebase, wait 5 more years. I've learnt that the hard way. For personal projects it is amazing though.
- veqq 4y agoThe best part of Julia for me is just that it has numeric primitives built in, so the different ML etc. libraries don't have to implement their own (incompatible) versions. So Julia code can be 1/10th the length in Python, because you literally just plug libraries together, instead of having to pipe distinct data structures together. It also means the libraries are short and easy to understand, instead of having tens of thousands of lines implementing said primitives etc.
- 331c8c71 4y ago> if you choose immutable structs, your interface for users is EXTREMELY annoying. For example, if they want to update `x` from `1` to be `2` That's the whole point of immutability that you can't "just update". I fail to see how obscure magical updates on immutable (?) structs like advertised in [1] or [2] e.g. using Accessors @set obj.a.b.c = d are beneficial. Note that there is _zero_ explanation on the front page of what the above snippet does, how to use it and what actually happens under the hood. One example of why I personally don't have much trust in JuliaLand. Scala has `x.copy(field=newval)` for its (immutable) case classes. Note how clear it is that one is making a copy. Lenses are also outside of the stdlib (e.g. [3]). [1] https://github.com/JuliaObjects/Accessors.jl https://github.com/JuliaObjects/Accessors.jl [2] https://github.com/jw3126/Setfield.jl https://github.com/jw3126/Setfield.jl [3] https://www.optics.dev/Monocle/ https://www.optics.dev/Monocle/
- JanisErdmanis 4y agoAs I understand, the idea of immutability and usage of packages like Setfield.jl to change struct fields is a safety feature for concurrency. When putting it in as an argument to a function, you can be sure that it would not be changed during execution introducing races without needing to acquire a lock. Also, state machines become easier to reason about when immutables are used.
- sundarurfriend 4y ago> I generally think a programming language should incentivize you to "do the right thing" > It is easier to create a immutable struct than a mutable struct This is exactly an implementation of that principle - since very often one of the goals when using Julia is performance, it makes sense to incentivize the more performant option. [1] > I'm incentivized to write `::String` instead of `::AbstractString`, `::Int` instead of `::Integer`. In Julia using `AbstractString` is almost always preferred. I'm on the fence about this one. I used to think this way, but now I think just slapping Abstract types everywhere in code leads only to fake-genericity. It's the sort of trap that leads to the kind of problems Yuri complained about in his (in)famous blog post. I'd rather someone type ::String and be artificially limited in what they accept (at least for now, until someone complains), rather than be incentivized to say they accept an abstract type and then end up not actually supporting all of the abstract type interface's flexibility. [1] https://docs.julialang.org/en/v1/manual/types/#Mutable-Composite-Types-1 https://docs.julialang.org/en/v1/manual/types/#Mutable-Compo...