Live data from Hacker News

Correctness and composability bugs in the Julia ecosystem

yuri.is

231–240 of 419 posts

Re: Correctness and composability bugs in the Julia ecosystem

#231

So this one is a tough one for me, because Yuri has certainly spent significant time with Julia and I think he's a very competent programmer, so his criticism is certainly to be taken seriously and I'm sad to hear he ended up with a sour opinion. There's a lot of different issues mentioned in the post, so I'm not really sure what angle to best go at it from, but let me give it a shot anyway. I think there's a couple…

FWIW my take is not that Yuri is expressing "there are too many bugs" so much as he's expressing a problem in the culture surrounding Julia itself:

> But systemic problems like this can rarely be solved from the bottom up, and my sense is that the project leadership does not agree that there is a serious correctness problem.

Concisely:

1. The ecosystem is poorly put together. (It's been produced by academics rather than professional software developers.)

2. The language provides few tools to guarantee correctness. (No static typing; no interfaces.)

Personally, what I'd love to see is one of the big tech companies come on board and just write their own ecosystem. The Julia language is amazing. The ecosystem needs to be rewritten.

Re: Correctness and composability bugs in the Julia ecosystem

#232

Earlier quoted context omitted.

There's a parallel idea, that you should avoid--insofar as is possible--numerical indexing. In other words, instead of iterating over `0:length(X) - 1` or `1:length(X)`, you use something like `for element in array` or indices = CartesianIndices(multidimensional_X) for index in indices X[index] = # whatever If you do that, you don't need to keep track of whether it's zero-based, one-based, or anything else. In fact,…

Works great for trivial cases where there's no interdependency between array elements. As soon as you need to access, for example, adjacent elements, you want to be able to just iterate over 1:length(X) - 1 and access a[i-1] and a[i]. This is the most direct way and thus easiest to get right. Abstractions only make it more error prone.

Is `for i in eachindex(X)` really any worse?

You can still do math on i, it avoids issues with OffsetArrays, and it might even be clearer why you're iterating. It requires that the array type support linear indexing, but so does doing anything sensible with X[i] and X[i-1].

Re: Correctness and composability bugs in the Julia ecosystem

#233

Earlier quoted context omitted.

`eachindex` is — in quite a few situations — faster than `1:n`. We've also been trying to promote a culture of not blindly putting `@inbounds` notations on things as the compiler gets smarter. `@inbounds` is a hack around a dumb compiler, especially when the loop is as simple as many of these examples. It's not needed there anymore (but was 5 years ago).

Perhaps that is part of the point of the article? If you accept things like @inbounds, which is a horrible hack and was a horrible hack five years ago, then perhaps the culture is a little too tolerant towards horrible hacks. Because many of the bugs the author enumerates are of the "fixes the problem for now, let's deal with the consequences later" type.

Yes and no... Julia's been focused on high performance numerical computing from the beginning (and other related scientific applications). Using macros to get good performance from relatively generic code was (from my outside perspective) a really effective way to support real applications early on and also give time for the compiler to get "sufficiently smart" to make the macros less necessary.

Re: Correctness and composability bugs in the Julia ecosystem

#234

Earlier quoted context omitted.

julia> pairs("François") |> collect 8-element Vector{Pair{Int64, Char}}: 1 => 'F' 2 => 'r' 3 => 'a' 4 => 'n' 5 => 'ç' 7 => 'o' 8 => 'i' 9 => 's' Notice the missing index 6, because ç takes two bytes. In contrast, enumerate() gets you the iteration number: julia> enumerate("François") |> collect 8-element Vector{Tuple{Int64, Char}}: (1, 'F') (2, 'r') (3, 'a') (4, 'n') (5, 'ç') (6, 'o') (7, 'i') (8, 's') This can trip…

Rust has the same problem with dealing with strings where if you don't realize how you are supposed to handle it with unicode you'll get burned when you don't correctly access code points. Edit: Also thank you for the answer. I have been curious about Julia even though I'm not a data science/ML type, but never find time. I do like to keep an eye on it though.

I haven’t used Rust, but Julia keeps you from getting burned too badly by giving you an informative error message if you try to index "inside" a character:

    julia> "François"[6]                                                                                       
    ERROR: StringIndexError: invalid index [6], valid nearby indices [5]=>'ç' [7]=>'o'
I’m not a data science type either. I came to Julia through physics and general computing. It’s the best language for science I’ve ever encountered.

Re: Correctness and composability bugs in the Julia ecosystem

#235

Earlier quoted context omitted.

C/C++ memory errors are literally responsible for 70% of ALL critical security bugs. Most python "dumb errors" can be caught by linters. Memory is infinitely harder. Source -- https://msrc-blog.microsoft.com/2019/07/16/a-proactive-appro...

And Python is implemented as a large C program.

66% python, 32% C - for cpython.

94% python, 5% C - for pypy.

Re: Correctness and composability bugs in the Julia ecosystem

#236

Everything has correctness issues somewhere. Julia ships an entire patched version of LLVM to fix correctness bugs in numerical methods. It has its own implementations of things like software-side FMA because the FMA implementation of Windows is incorrect: https://github.com/JuliaLang/julia/pull/43530 . Core Julia devs are now the maintainers of things like libuv because of how much had to be fixed there. So from tho…

> Everything has correctness issues somewhere.

This is fallacy of gray. The blog post isn't complaining that there are non-zero bugs, it's complaining that when you use the language you hit a lot of correctness bugs. More bugs than you'd hit using e.g. python.

Also, to the extent that Julia uses LLVM, a correctness bug in LLVM is also a correctness bug in Julia. So arguing "LLVM has lots of correctness bugs" is not helping the case...

> because the code is all Julia, it's really easy to dig in there and find potential bugs.

The blog post is about bugs hit while running code, not bugs found while reading code. The fact the issue can be understood and pointed at is great, but it's the number of issues being hit that's the problem.

Re: Correctness and composability bugs in the Julia ecosystem

#237
Correctness in Julia feels like it'll never happen, because interfaces seem like they'll never happen.

Correctness guarantees / interfaces and slow startup are both my biggest pain points in Julia.

I often think what would happen if every Julia dev just dropped the language and used Rust instead. A scientific ecosystem in Rust would be amazing.

Re: Correctness and composability bugs in the Julia ecosystem

#238

Earlier quoted context omitted.

You may already know of it, but if you want differential-equations-in-JAX then allow me to quickly advertise Diffrax: https://github.com/patrick-kidger/diffrax (of which I am the author, disclaimer).

Yes I am aware :) it is missing a few things but I might end up contributing.

Excellent! I'm very happy to take contributions generalising the tool.

Re: Correctness and composability bugs in the Julia ecosystem

#239

So this one is a tough one for me, because Yuri has certainly spent significant time with Julia and I think he's a very competent programmer, so his criticism is certainly to be taken seriously and I'm sad to hear he ended up with a sour opinion. There's a lot of different issues mentioned in the post, so I'm not really sure what angle to best go at it from, but let me give it a shot anyway. I think there's a couple…

The big language design problem that I think this post highlights is that the flip side of Julia's composability is that composing generic code with types that implement abstractions can easily expose bugs when the caller and the callee don't agree on exactly what the abstraction is. Several of the bugs that Yuri reported are a very specific case of this: there's a lot of generic code that assumes that array indexing…

> 2) you can find out what methods you need to implement just by running the code that uses the implementation and see what fails.

For large codebases this is SO painful to do. I just don't understand how anyone gets anything done when this is how they have to develop code.

Re: Correctness and composability bugs in the Julia ecosystem

#240

Earlier quoted context omitted.

The big language design problem that I think this post highlights is that the flip side of Julia's composability is that composing generic code with types that implement abstractions can easily expose bugs when the caller and the callee don't agree on exactly what the abstraction is. Several of the bugs that Yuri reported are a very specific case of this: there's a lot of generic code that assumes that array indexing…

> 2) you can find out what methods you need to implement just by running the code that uses the implementation and see what fails. For large codebases this is SO painful to do. I just don't understand how anyone gets anything done when this is how they have to develop code.

That's why interfaces are useful—they save you from that. But they don't actually solve the problem of checking that an abstraction has been implemented correctly, just that you've implemented the entire API surface area, possibly incorrectly. Note, however, that if you have a way of automatically testing the behavioral correctness of an implementation, then those tests presumably cover the entire API, so automatic testing would subsume the benefit that static interface checking provides—just run the automatic tests and it tells you what you haven't implemented as well as what you may have implemented incorrectly.
Post reply on HN