We as a community should be more understanding of Julia's flaws

Technically, the line is “Julia is an expressive language like Python is”, not that it is as easy (well, type-based dispatching is easier in Julia for obvious reasons). But practically, you are right that a lot of people come into Julia expecting to do classes and inheritance rather than annotating fields in structs and dispatching generic methods for type stability; they don’t seem to realize that Python’s runtime type checking is a big reason it’s so hard to optimize.

Maybe it would help if more first-time Julia examples showcased what’s different from Python? So rather than just showing f(x) = g(x, h(x)) + 3 and saying the compiler’s type inference takes care of things, you’d show how you can have some important manual control over type inference, like struct Wrapped{T} inside::T end and initializing an accumulating loop with result = zero(eltype(A)). That said, most introductory learning sources have done this, but I’m guessing many people have not read those before throwing themselves into writing a script, so I think it would help if the casually quoted examples also look more Julian.

Blaise Pascal on “correction” is a classic (pls excuse historical pronoun gender)
“When we wish to correct with advantage, and to show another that he errs, we must notice from what side he views the matter, for on that side it is usually true, and admit that truth to him, but reveal to him the side on which it is false. He is satisfied with that, for he sees that he was not mistaken, and that he only failed to see all sides. Now, no one is offended at not seeing everything; but one does not like to be mistaken, and that perhaps arises from the fact that man naturally cannot see everything, and that naturally he cannot err in the side he looks at, since the perceptions of our senses are always true.”

21 Likes

Just wanted to drop this link here as your comment was one of the reasons why I thought it would be worth to write this post:

https://jkrumbiegel.com/pages/2022-08-26-pkg-introduction/

19 Likes

I totally agree that conflating these is most probably wrong, but I also think the marketing issue has popped up fast in the thread for a good reason: the two aspects are intimately related imho, more than what I feel the general consensus here is.

As an actual outsider of the language (have wrote less than 1000 lines of Julia yet, but gravitating around with fluctuant interest) I actually believe that in some sense you, as a community, should choose which of the two aspects (marketing vs social “aggression”) you want to “be a problem” and let the other be “all good”, since they are kind of complementary. If people are bringing up marketing and expectations here is maybe just because they do not agree on this implicit “choice” about which of the two is the main issue.

Going explicit on “how and why” they are complementary, let’s take one of the forms of the “solved 2-lang problem” slogan: faster than c++, easier than python.

  • if you want this to be a reality (maybe with “as mush as” formula instead of “more than”, ok) then you should totally avoid bashing people for “allocating like crazy” (on a personal note, I also find exactly this kind of mocking tone strongly pushing me back from the community), since keeping attention to this level of details --maybe even worse with type stability-- greatly moves away from the “python-like easy” perception.

  • but you can very well prefer to hold the position that a user that wants performance would inevitably need to dive deep in such critical details, and so you would rather keep your “right” to explain why the user is failing to code idiomatically (or even appropriately in general for the problem at hand) and suggest to investigate more on these fundamental quirks before complaining about supposed flaws of the language. (in a kind way, of course, about tone I see no excuses and I’m quite happy about the consensus here)

From this latter perspective, I think one should seriously consider to drop the vision (if not even a claim that we are already there) of a language that’s at the same time easy, dynamic, remarkably expressive and outstandingly performant.

Let’s be clear I think Julia can be each of these, there is much evidence about best-in-class speed, it’s quite easy to demonstrate a huge degree of dynamism and we all know how much expressive mutiple dispatch can be. But after reading many many discussion here I got that you can’t have the whole cake, every time people has performance issues the advice inevitably lowers to “reduce drastically your dynamism, maybe even freeze it all”.

I actually think it’s very very very nice that Julia allows you to have both styles and to exploit the wild dynamism while fast prototyping, and then optimize the production code by just polishing and giving dynamism up afterwards and where is relevant, without needing to switch language (and so style) all together for everything. In this sense yes, the 2-lang problem is solved, I agree. But I don’t think all these slogans, in any form, really deliver this exact message. People really expect instead to have both dynamism (et. al) and bare-metal performance working together and I just fail to see that happening anywhere near in the future. Like really, a language that is actually extremely dynamic and at the same time blazing fast is a huge promise, and a beautiful (greedy? semicit.) one.

Some time ago there was a very long thread, “Claim (false): Julia isn’t multiple dispatch but overloading” and while I agree with the general community response (Julia is totally able to dispatch at runtime and has no notion of static types, so that’s the semantics in the language) I find the critique had an hidden bit of truth: you can have runtime multiple dispatch and it opens wonders about composability but then you have inevitable performance pitfalls, unless you tame the actual runtime nature. So, apparently, what you all really want as the “unreasonable driver of julia success” (semicit.) is actually static “inferrable” multiple dispatch, very similar to overloading, in many ways. Again all communication about multiple dispatch focuses strongly on its inherent dynamic nature but any performance advice screams at you “no! do not touch the marvelous toy I just praised to you, bad kid”. So people feel betrayed in their expectations, you had promised a golden apple, you are afterwards mocked for believing it too much. Managing expectations would go quite a long way on perception and probably remove many “dumb questions” from your daily discourse walk: something like “we have something more powerful than static overloading since compile time is intermixed with runtime and you can have a fair bit of dynamism on your dispatch but beware, you have to carefully dose how much dynamism you put in to avoid serious performance pitfalls” sounds quite better than “multiple dispatch unleashes powerful dynamic composability within a C-speed language… oh, you have crazy type instability, how you dare complaining about performance, you dumb”, doesn’t it?

Sorry for the very long comment, I initially intended to be way more concise. I would like to give it an end by noting that from comments like

I understand that some of you may be aligned with the latter “worldview” (as I am, in general, for whatever performance-oriented language) but this to me is in fair conflict with statements like

if the aggressive marketing keeps relying on the “both easy and performant” adage. (sorry @jacobusmmsmit, did not really want to take both quotes from you, they are just an example of the friction I see here). The claims are well substantiated as far as performance goes, but not really if you expect that much easy of usage in the same code.

9 Likes

Hot take: we are too worried about perceptions on hacker news. Hardly anyone reads hacker news, and people that do are not necessarily the target audience of Julia.

As a counterpoint, this youtube video is approaching 400,000 views and has 1000 comments, mostly positive. There is probably more to learn by reading these, as new julia users from channels like this will outweigh people coming from hacker news. Probably by a lot.

19 Likes

In 2015, HN got

Roughly 2.6M views a day, 300K daily uniques, 3 to 3.5M monthly uniques.

and the number of daily requests was around 6M in 2021.

3 Likes

For what it’s worth, in my recent post comparing JAX and Julia the first thing I say is that both are advanced tools.

The difficulty of mastery, and frustration new users can face compared to more forgiving languages, is a large part of why I call Julia’s claims mostly substantiated. :slight_smile:

1 Like

Fireship’s audience is majority webdev/undergrads and inexperienced though. I would hedge my bets to say that most of them are in the very early stage of learning Julia where they follow carefully scripted tutorials (which I’m so glad to exist) that hide some of the harder aspects in the language.

3 Likes

300k daily uniques is not huge for a website (even compared to individual Reddit programming subs), and hardly any of those HN views are people reading about Julia.

400k on one single video in a few months looks pretty good in comparision.

@jacobusmmsmit I totally agree, but IMHO those are people more likely to use Julia than HN devs. Most scientists are inexperienced programmers.

1 Like

Fwiw, the Fortran video has more views (and was released later). What does that mean, I have no idea. What I know is that is that for 20 years I never heard of any of these sites, and neither did many people I worked and collaborated with. I do think then that all these impressions are overrated.

I think you made good points there, except this one. There is hardly any need to reduce dynamism because of the power of generics. The dynamism has to be controlled for the input types of procedures only, in a specific way, which hardly limits the functionality at all. It is not comparable to what one is restricted to in languages without generics and multiple dispatch.

But there are gotchas, and one will, for sure, fall into them, many many times, even after gaining experience. It is not an ride without bumps, that’s for sure. Julia will be easier and more satisfying to use when/if a powerful and very user friendly linter becomes available.

7 Likes

Oh ok, I think I may have miscommunicated here. With dynamism I refer to uninferrable runtime magic, which is what a good part of the Julia hype is about imo. Generics, at least in their C++ incarnation, are resolved at compile time and need full inferrability of types so yes, I agree that Julia has its perfect means of achieving what templates do. Again, deal with templates is not exactly sold as “very easy but runs like bare C” in the C++ community, more like “accept to add quite an amount of complexity and nightmare to unleash the power of generic programming” which is exactly how I see jumping to Julia from say Fortran.

I was wondering what you meant by dynamism, I don’t think the above is what first comes to mind for many. When I hear ‘dynamism’ I think expressiveness mixed with genericity/polymorphism. And these you can have, mostly with little or even no negative impact on performance.

I don’t think so, or, at least I must have missed that. “uninferrable runtime magic” is something to be avoided, afaik.

But the claim is that generic programming with multiple dispatch is dramatically easier than C++ templates. I wouldn’t know myself, but I’ve never heard anyone claim otherwise.

Personally, I think it would be better to market Julia as a more advanced language than Python, with more to learn, instead of simply ‘as easy as’. Even if Julia were every bit as simple as Python, people would still disagree, because learning a new language is unavoidably harder than continuing with the one you know. Any difference makes the new language ‘harder’.

3 Likes

That’s my point really, that was just one video I randomly saw.

We just need to remember that other forums have far more engagement with future users than the heated duscussions on HN posts (or here), that people are concerned about. And that even holds for Fortran.

1 Like

My other experience is with Fortran, I and I find Julia easier in general.

If one sticks to “simple” Fortran (i.e. something like what F77 offered) it is very robust against user mistakes. But also very limited. If one uses all modern features it gets much more interesting but more complex as well.

Generic programming for simple types is very easy, I would say automatic for the user, in Julia. It gets more demanding if one wants to support units, auto diff, etc, but it is another level of composabilty, and not that hard either.

oh god this has gotten so long, I’m truly sorry :grimacing:


I think this really hits the core of the perception issue, thanks for this valuable perspective!

As someone who chiefly falls in the camp of “know your tools and use them effectively”, I’m a bit conflicted about the perception. Quite frankly, I don’t like the “as easy as python” part one bit, for one because it implies that Python itself is easy and for another because it effectively says that writing fast code in julia is the same as writing fast code in python, neither of which is true. The mental models are, depending on your situation and prior knowledge, very far removed from one another. The problem is that bad performance often seems to come from a lack of knowledge about what makes code (not just julia code!) slow in general, which some languages manage to mask more than others, while some of the reasons are only applicable to some languages in the first place (think type stability). A priori this is fine, as long as it’s kept in mind that habits from one language don’t necessarily translate to another.

I think that getting from naive Python performance to pretty good julia performance (perhaps not C/C++ equal) is easier/more accessible than getting the same speedup in python. The downside is of course that due to the difference in mental model, patterns that already make fast code in python may make horrendously slow code in julia, due to e.g. slicing & allocations… At which point it’s really hard not to say “well you’re allocating a lot”. I’m certainly guilty of this and would like to do better here, but it’s hard to know how when that’s the core of the problem with their code :confused: I have done detailed deep-dives with explicit annotations about which part of someones code is causing a slowdown and why, but these sorts of analysis take a surprising amount of time and effort, even though they’re much better at conveying the “why is it slow” & “how to make it not slow”. That’s not to say that the “rules” for writing fast code are especially tricky, far from it, but it’s obvious that they clash with the perception of “as fast as C, as easy as python” (even though python also has such rules, they’re just not as prevalent and/or more easily shoved into C, where the language itself forces people to think about more or less the same things you’d have to for high performance julia).

I’d like to suggest a better narrative, but I’m at a point where I don’t think referring to python or C for any sort of “simple” comparison is a good idea. Even something as innocuous as “Easy as python, with some effort as fast as C” again implies that julia or python are easy to learn, which they most certainly are not, in spite of python being taught in beginner programming courses. There’s just too many things to keep in your head for any newcomer to not be overwhelmed in either.

From my POV at least, this was never the case, but that may be due to me having a background in CS and already knowing why that is hard and why Python doesn’t achieve it. So when I encountered julia and my mental model of programming languages was “there’s code I can compile to an .exe and there’s scripts I have to run like interpreter myfile.foo”, I was gobsmacked when I found out that julia is started like the latter, but can still have the performance of the former. That, even from a CS POV, made absolutely no sense to me. Only after I learned that the computational model of julia is more like (repeatedly) compiling code as a static language does and feeding the source code in like an interpreted language, did it make sense how (and when) julia was fast.

That’s the crux of the issue though: to have fast julia code in no small part requires thinking about writing code like you’d do in a static language. If you’ve never been exposed to that side of programming, of course you’re going to struggle with writing “bad” code that’s maybe interspersed with idioms that are not a problem in e.g. Python because there the whole language/ecosystem is (though its users may not be) aware of the fact that python is a dynamic language, with a dynamic interpreter and more or less anything can happen at any time. It’s marrying those static & dynamic parts in one language that presents this challenge of not really being able to easily get out of requiring lower-level (and general CS) knowledge to write effective code at all. So while julia advertises itself more as a dynamic language, at its core julia is extremely close to being a static language. To someone who doesn’t know static languages at all, the gap between why certain dynamic patterns are bad and why adding a seemingly magic ::Int in a struct is good, but ::Integer is bad, can be huge. It’s this gap that, I think, we should be better at communicating upfront (to prevent people thinking of us as doing false advertising), better at educating people about what & more importantly WHY we code like we do (easier said then done, that can easily cover a semester alone), and overall be more mindful of when trying to help someone who’s confused about why their code is slow when julia has been advertised as fast (that’s the one point I refuse to give in on).

On the upside (and to not feel like I’m posting doom & gloom about others’ perception of julia), IF we manage to be better here and pull it off, we’re going to end up with more people knowing how the computers they’re using to do their daily scientific work actually work, which (I believe) will make us all more effective at what we’re doing :slight_smile: It does require of us to be mindful of this gap I mentioned though, and to make sure we identify when we unintentionally assume too much of the other people we’re interacting with (but don’t assume they’re idiots either - try to identify where they fall on the static<->dynamic knowledge/familiarity graph and word your answers appropriately).

10 Likes

Unfortunately decisions are more likely to be taken by management than by users, and these people have started to read HN.

I would go a little bit further: in requires one learning aspects of programming that we might never been exposed to in other languages, including some static ones (like Fortran).

In some sense, the issues arise on how much the language imposes its style to the programmer. Some languages impose so much that shield the programmer from a lot of these concepts. Fortran is one of those, you can be a completely newbie and will not write a program that allocates like crazy, nor you will be even exposed that problem of creating boxed temporaries, probably. Python imposes so little that doing anything performant requires using libraries, which then impose a lot to the user, to the point that one has to rethink completely the problems to adapt the constructs to the interface of the library. Julia is a midterm: it does not impose the style, like python, but it requires a style to achieve some goals. In that sense it is more complex than these alternatives, and is the user is more left alone.

I still think that tooling is the path to improve this experience, having great linters to point to bad patterns is what will make it easier to learn and use Julia effectively. JET is on that way, just the output is intimidating.

4 Likes

Yes, I could anticipate this from you of course. I feel like I don’t really agree but having not really put my hands on julia I might be biased. One thing I would like to point out is that modern fortran can well stay quite away from heavy OOP patterns (which are so much pervasive in current modernized ecosystem that I fear could be identified with the whole modern fortran keyword). I don’t like OOP and find it often adding unnecessary complexity to otherwise simple things so maybe there is where we agree.

But you can do so much with interface-based static overloading that I do not really feel I miss something (other than templating maybe, that “just” lets the compiler expand the boilerplate for you, but I’m not sure about the cost/advantage balance for my personal needs). Of course that requires everything to be inferrable at (ahead of time) compile time which is indeed limiting, but then you always have unlimited polymorphic declarations (class(*) and even rank(..) from f2018) and the select type/rank construct if you ever need a fair bit of non-trivial runtime dispatch (potentially you can do whatever you want, but that requires arbitrary deep nesting so yes, is half-baked for now). This brings me to:

I think that coming from maltab/python/R you probably take dynamism for granted and then find that Julia makes it much more systematic and ergonomic, and that should have a strong “wow effect”, but if you come instead from static languages you already have that for the inferrable cases, and get probably hyped by the uninferrable dynamic part, which you may have in the static language, but for sure less ergonomic than static overloading, which is why I agree with this:

1 Like

But then (sorry, I pressed the publish button too early cause I’m actually at the beach and cannot see well on the screen :see_no_evil:), if this usage of unferrable dynamism is heavily detrimental I, as one who would come from modern fortran, would wonder why not just settle for static overloading. For one reason surely staying where you already are is the path of least resistance, if you are not pushed hard by benefits (tough note that I’m fairly young and being working in fortran since just 2 years), but also static analysis brings to the table a whole bunch of benefits, that I find hard to give up for something that I cannot really see as a ground breaking improvement over overloading. So yes, I agree very much with Leandro here:

Give Julia a powerful static analysis tool and I would probably hop on board, give modern fortran an interactive workflow (it’s slowly coming…) and some syntactic sugar for select type/rank based multiple dispatch and I will stay there forever.

As a final note:

I don’t agree at all with this: goto statements and all that legacy machinery is far from robust against human mistakes, maybe you were referring more to F90-ish workflow, which ultimately amounts to static overloading. I don’t have really clear the details of diffs between fortran releases, but now for sure you can stay very simple and redefine the same function many times (different name, that I recognize is more ergonomic in Julia) with different declared input types and then build an explicit interface (which is just a list of the various implementation, wrapped to one single name, which I understood Julia does implicitly) and have all the polymorphism you want, as long as the compiler can figure out the dispatch by inferring what you feed in the call. Once you go JIT (again, it’s coming) I see no real differences to the “tamed” multiple dispatch in Julia. The explicit interface, while admittedly annoying to write, makes actually easier to track where you are dispatching, since you have a list of all implementations put together in one place. If you wonder about inter-package composability I believe you could just import the interface common name from the external module, aliasing it with a slightly different name (its name with a module name prepended for example) and then just define your own implementations end build another interface. Julia makes it more comfy for sure, and I like that, but the big promise I saw was to have something completely different in its runtime capabilities.

It’a a good short video, except for the misleading (at 1:02) “get started install Julia” on floppy disk?! :slight_smile: Not possible, while you CAN compile some Julia code to binary 10 KB .exe, so would fit there…