I believe the “overstated” part was the unqualified “its main practical goals are failed”. Your disappointment in a v0 tool is valid, but claiming the tool is the main goal of the utilized programming language is inaccurate, and dismissing the language is hyperbolic. It wasn’t hard to look up the many real-world applications of Haskell; even niche things have their impacts.
The issue is this doesn’t only depend on the
AbstractArray type; it depends on what
AbstractArray generic methods you need and where they come from. I could make a module of
AbstractArray methods that only use the interface method
length, and if for some reason you only need my module,
length is the only thing you need to implement. Note that despite its primary role in my module,
length is documented “optional” and defaults to depending on
size in Base Julia.
required_methods would require a list of desired function calls (your test suite in a sense), the modules they came from, and some module-wise designation of important interface methods. It would do part of the compilation process to recursively figure out all the unimplemented methods, then intersect those with the exhaustive set of designated interface methods. That granularity is complicated and time-consuming, it is much simpler to stick with the status quo of documenting the intended interface per package/project. For sanity’s sake, a project should not unilaterally introduce new interface methods to an interface it didn’t create, which effectively changes its meaning.
I’ve recently been chatting about Julia, and somebody made some comments that I think would fit well here:
I have a serious discoverability problem with Julia. Or perhaps Julia has the problem. The manual explaining Julia concepts is pretty good, but the documentation for most packages I need to use is inadequate. There’s a lot of friction even when doing simple things. For example, I can’t get keyword argument completion for functions with Eglot. I don’t remember how to manipulate
plotfeatures, and it’s off to the Plots.jl documentation for me every single time.
(Keyword argument completion is available with Python’s LSP implementation for me.) The Plots.jl docs are a good example of Julia’s almost-but-not-quite problem. It takes me forever to find what I’m looking for on there, (again) every single time. I’m not sure why. The second issue with Julia is that the names for functions aren’t great. Or at least not consistent. I use Mathematica once every few months, but between the auto-completion and the consistent CamelCase naming scheme I never have to leave the Notebook interface to find (or remember) what I want.
The package ecosystem is bewildering. Not its mechanics, it appears to be well engineered and documented in the manual. It’s learnt from Python’s mistakes, at least. I mean searching for, deciding on and using an (often poorly documented) package to solve a problem is a painful task, especially since replacements spring up all the time. I’d like to get to the point where I can appreciate the much celebrated serendipities of Julia’s design. But the language+ecosystem wears me down every time I try to use it for a project.
I agree that finding and using keyword arguments is frustrating. They are often only documented as
f(;kwargs...), so I have to dig through examples until I find one that uses the keywords I was looking for. Even once you find the correct keyword, what are all the possible values it can take? There are few packages that document this adequately.
This message is full of interesting points, and I believe most are addressable in the short term.
There seems to be a more fundamental point, however, that having autocompletion is easier for object-oriented languages (where each object has a list of methods), and that is challenging to do it right for Julia.
But in the documentation and package-discoverability area we could see some improvements with perhaps little effort.
I fully agree!
I am trying to create something like a friendly user guide for Plots.jl, which selects a subset of the most commonly used features and presents them together nicely:
Ideally, something way better than my post should be produced, but it would take some time. This is also incomplete.
I also agree. The development of big meta-packages (like SciML) is probably one way to go here. The other is just to wait for small bloggers (like me) create some tutorials, and then let the Google machine do its job in surfacing the best content.
Yuri’s post and the enormous backslash made me doubt Julia a bit. However, after a few weeks, I realized that there is no problem. The fundamentals are still fine:
Feedback and comments are welcome. Doesn’t have to be in this thread; feel free to contact me personally.
Instead, I’d say that there is a huge combination of packages that can be used together providing the language with an enormous amount of possibilities.
This is insightful – there are perhaps a nearly infinite number of package combinations that won’t work together. However, a very large number of packages will work together – this is the interesting and productive space to work in.
Also, you note the advantage of a single package manager. You undersell it! It is an excellent package manager, perhaps best in class. The multithreaded compilation is a cherry on top of its overall excellence.
As someone pointed above, part of the problem stems from the lack of incentive for developers (which are mostly from the academic world) to properly document, add tests and continuously maintain packages and fix bugs. More often than not, once a package works as intended for that particular researcher, that’s it, development is over. Perhaps the Julia problem being adressed here is not with the language itself, not a code problem. Perhaps it’s more of an “ecosystem”, “macro-scale” problem: how can we incentivize developers to continuously adress the interfaces between packages, solve bugs and go over PRs?
It is similar in R especially Bioconductor packages, don’t know for Python. But for me the huge advantage of Julia is here that typically packages are written in Julia (and not in C, like for R). So, this specific property of the Julia eco system, makes me prefer Julia over other languages, because I can solve my specific problem partly with existing packages and from there I can proceed much more easily.
This is my main personal “Julia solves the 2 language problem” (among others).
Of course Julia has some issues (more or less depending on taste), but it also has quite some advantages. Like every language. In this aspect, the conclusion “I no longer recommend Julia” doesn’t make too much sense, as nobody recommends any language without some "But"s, because at the end, there is no perfect language (yet). I am pretty sure, that the main and most serious issue, that “Julia results are silently incorrect (OffsetArrays as example)”, can be constructed for every language and it’s eco system.
Not saying, it shouldn’t be addressed, just saying, it’s likely to find such issues in younger languages. Concluding not to recommend this language in a general sense is overly dramatic. There are languages which shouldn’t be recommended for real world tasks in general, but Julia is not one of those esoteric languages.
It’s ironic that this post has been up for a month and a half now, and has received immense attention across various forums (including 250+ comments in this thread), but Yuri is still pointing out indexing bugs such as `first` sometimes returns incorrect results when used with nonstandard indexing · Issue #45842 · JuliaLang/julia · GitHub and BitArray "constructor" incorrectly assumes 1-based indexing, leading to nondeterministic incorrect results due to out-of-bounds memory access · Issue #45825 · JuliaLang/julia · GitHub. Both of these might have been detected by a simple
@inbounds. Yet, people are busy debating on broader ideas instead of acting on issues that the original post had raised.
Note that (at least for the first one), the
@inbounds call is safe. The problem is a just an integer overflow.
But, both of those were acted on. Haven’t all the raised issues been acted on, as far as possible? I mean, except for some of the broader issues…
Guessing you did that simple grep for
@inbounds yourself already then, and you’re filing issues as I type?
13 posts were split to a new topic: Workflow challenges with redefining structs (from “Why I still recommend Julia”)
Agree with you.
My solution is just using PyCall.jl and importing matplotlib.pyplot, since mpl has a very detailed documentation.
Yes, the response of the community to resolving filed issues has been fantastic, but my point was more about finding the issues in the first place, in which Yuri seems to be the one taking the lead. I wish more people would participate in this.
As a matter of fact, yes Fix overflow in `searchsorted*` by jishnub · Pull Request #286 · JuliaArrays/OffsetArrays.jl · GitHub, Integer overflow in `reverse!` for an `OffsetArray` · Issue #45870 · JuliaLang/julia · GitHub
Haha that’s awesome, thanks for putting in the time. Unfortunately it does end up being whoever feels the strongest about problems that has to fix them a lot of the time.
I do think people are responding to the post seriously, but open source is slow and we’re all busy.
For example I’ve got the start of an Interfaces.jl package written to formalise interface testing (or at least provide some ideas for it), that was the part of the discussion I felt the strongest about. But it will be a few months at least until I can actually register it.
Very well written article! I do have one point of criticism – the description of object-oriented programming. It is such a common mistake to make, given that not very many people are familiar with older OOP implementations. Common Lisp as an example, does not couple methods to classes. It behaves in a very similar way to that of Julia, except multiple dispatch methods in Common Lisp define behavior for classes, not types. Additionally, the rules in how the most applicable method is chosen can be customized and extended with the meta-object protocol. Infact, the entire OOP system can be extended in this way, in the same way macros allow you to extend the language’s syntax. Mind you, Common Lisp’s object system is more than a decade older than Java, and more than 5 years older than Python – two extremely popular object-oriented programming languages. Object-oriented programming does not imply methods belong to classes; it simply means that collections of data can be represented as user-defined constructs that can be extended through inheritance. This more general description covers more languages than Common Lisp, too.
Julia does take it a step further though, and declares that every function be a method, and that they operate on types (which have an infinite domain as compared to classes).
Overall, great article. I just wanted to point this out because it is something I see all too often that bugs me, as a former Common Lisp developer.
That’s why I sticked to the Java, C#, C++ definition of OOP. Most people think of that flavor when talking about OOP. I’ve considered adding some footnote in the blog about that OOP is not strictly correctly implemented in modern languages, but that seemed to distract from the main story. By “correctly implemented”, I mean implemented according to the definition by the original creator of OOP. There is a nice talk on YouTube somewhere by the original creator. Maybe it was on a Smalltalk conference? He tells how everyone got OOP wrong. Can’t find it now, maybe you know the one
But… Then what’s the difference between types and classes? I thought classes where types with methods in them.