Comparing with Python

It’s helpful for everyone here to get reminded of a Julia beginner’s perspective, so thanks for writing that up. My comments on two of your points:

  1. Ease of learning. Python wins, hands down.

I think we need to distinguish between availability of learning materials and ease of learning the language itself. If the former, it’s no contest. If the latter, I think Julia wins hands down. I spent about a month each with Julia and Python about two years ago. Objects vs dispatch was about a wash for me (at that time, now I’m sold on dispatch), but getting the syntax for calculations right with Python was very rough indeed, and I found the end result ugly and hard to read. So I went with Julia and never looked back.

Although I think it’s easier to learn (and work with) the basics in Julia, it may be harder to become really good at Julia. I’m still struggling with designing good types for optimization models (e.g. for passing around many parameters and JuMP variables).

julia> max([1,2,3])
ERROR: MethodError: no method matching max(::Array{Int64,1})

I strongly agree that error messages and the REPL help function need improvement, preferably before all the v1.0 beginners show up. At the very least there should be pointers to related functions in the help. It’s borderline criminal that neither that error message nor the REPL help suggest that you may have meant maximum(). EDIT. I don’t know how I missed it, it’s only one tiny line of text. I guess it’s a TGIF thing. I still think we need more pointers to related stuff though.

4 Likes

I’m going to go with @tomf on this one, if I’m being honest with myself I really do think Julia is harder to learn than Python, in some sense, particularly given the dominance of OO programming languages. That said, I absolutely love the parts of Julia that are probably mostly responsible for making it harder to learn (e.g. complicated dispatch patterns).

I’m going to go out on a limb here and take it one step further to say that I’ve grown to really love method errors. I feel like they tell me so much about what’s going on. Just for the hell of it, I did max([1,2,3], 2) in the 0.7 REPL and I got this:

ERROR: MethodError: no method matching isless(::Int64, ::Array{Int64,1})
Closest candidates are:
  isless(::Missing, ::Any) at missing.jl:66
  isless(::Real, ::AbstractFloat) at operators.jl:147
  isless(::Real, ::Real) at operators.jl:335

Wow, that just makes so much sense. Clearly max uses isless for ordering. Obviously isless makes no sense when called on these types, but it does make sense on the types in the methods listed. Now I might assume that if I create a new type and implement isless that max will work also. And, just for good measure, I can do

@edit max([1,2,3],2)

I’ve gotten a lot of really fantastic information here with absolutely 0 effort.

By comparison, in Python I get

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() > list()

That’s a perfectly fine error message for sure, but it gives me a lot less information than the Julia error. I now no absolutely nothing about the internals of Python’s max other than that you can’t order an int and a list.

I certainly concede that these errors may seem a bit arcane to someone new to Julia, but give it some time, you may come to like them.

2 Likes

I personally think that Julia is much easier to learn if an user haS exposure to Matlab or Fortran.

https://cheatsheets.quantecon.org/

I used to consider Python as a poor man’s C++. Many people learn Python first and then C++.

6 Likes

Good example. That error message is quite useful for an experienced user but horrible for a beginner. (“What??? I didn’t call isless() there. What does that even do?”)

IMO a more useful message for a beginner would be something like:

The max() function has no method defined on array arguments.
Try broadcasting the function over the array instead, i.e.
    max.([1,2,3], 2)

Of course that is much less useful for the pros. Would it be possible to have a beginner’s mode? Or somehow be able to get more explanatory error messages on demand?

1 Like

Users will come. I just convinced 4 persons around me in the last weeks. :family_man_man_boy_boy:

3 Likes

I’ll definitely concede that.

Maybe someone can do an experiment with Cassette to see if they can intercept errors or something like that, might be an amusing project.

Nice, that’s a much better track record than I’ve had. One of my colleagues who works on large scale constrained optimizations was very easy to convince that Julia and JuMP are far superior to anything available in Python. He’s understandably nervous about maintenance, but agrees that ultimately we should migrate everything to Julia. The rest of my colleagues and my mechanical engineering friends have been totally indifferent.

This is in data science in private industry however, I probably would have had lots of luck while I was still in high energy physics, though the need to compile Julia to use Cxx.jl would have been a major pain point.

I’ve never written a C extension. Nearly every low-level thing I want to run fast has been written for me.

People choose high-level languages (Python, Ruby, Julia) because they want to concentrate on their problems and be able to prototype solutions quickly. Julia promised me a high-level language with low-level language speeds. Sounds like a great deal. After all, if I could put up with verbose declarations I’d be using Java.

Worrying about things like type stability and unions being inefficient (and even having to declare unions at all) may seem natural to you but it’s not part of the problem I’m trying to solve. I want the compiler to handle it. As a CS guy I understand why type instability slows execution, but as a language user it’s ludicrous that simply adding a new return clause to a function should have a big effect. So the “optionality” of Julia’s type declarations comes with strings attached: if I ignore them I don’t get the speed I was told about, and this doesn’t seem like such a great deal any more.

-Tom

PS. Classes are optional in Python. Using them or not has little impact on performance or anything else.

1 Like

I said I wasn’t trying to start a flame war and I’m not. I genuinely appreciate people’s comments. I’m just a whiner. :slight_smile:

-Tom

Type unstable code works fine in julia, no need to worry if you are satisfied with python like performance. If you want fortran like performace, you need to worry about a few things. There are no miracles. The point is that you can develop fast code a bit easier in julia than in python. Anyway, guys like you will not need to worry about anything when infrastructure will become little more developed. You just take a package and use it.

1 Like

That’s why I’d like to see at some point the parser and lowering code done in Julia, and much of the LLVM IR code also rewritten in Julia.
I’m planning on eliminating the need for the C utf8proc code for dealing with Unicode (at first in my Strs package, hopefully later Julia itself can adopt it)

Where they might benefit with Julia, is if there is a library in Python they wanted to use, another one in C++, and another one in R, for example.
It may be that the easiest way to bind together functionality from different languages would be using Julia as the “One Ring” to bind them all.

Lucky. Or unlucky if you’re a methods researcher :wink:. But I think that’s a good explanation for why there might be a disconnect between you and a lot of Julia users. A lot of people come to Julia because that statement is false for them and that’s where the issues begin. When this statement is true for someone, there is a lot less of an incentive to come to Julia since the key advantage is the ability to productively build performant packages. I don’t think we have to target everyone in Python/R/MATLAB since existing code is fine.

Julia is good for the people who are researching methods, and over time as these new methods catch on with Julia-first implementations that’s what causes methods users to switch.

5 Likes

Type unstable Julia code still has much better performance than Python.

I seldom spend much time worrying about type stability. Most of my code is type stable anyway without any special effort, this’ll be true for most people most of the time. Occasionally I really need something to be fast and find that I inadvertently wrote some type-unstable code, and I have to go back and fix it. Writing efficient code is hard in any language, but Julia gives you a big head start.

Yes, that’s exactly what I was saying: classes are optional in Python, and type assertions are optional in Julia. Each of these things are needed for writing complex code in their respective language. Python classes have strictly worse performance than those implemented in C. Try writing some special array class in pure Python that gets equivalent performance to its numpy equivalent, see how far you get.

To expand on @ChrisRackauckas’s point, one of the things that drives me crazy about Python is I don’t want somebody else telling me where the boundary has to be between the efficient low level code and the code that I’m writing. Sometimes you start out with something benign and wind up with something really nasty, and sometimes that doesn’t happen all at once. In Julia I can fill a 10 million row dataframe with some custom types that I wrote that do all sorts of useful things, I don’t have to worry about them having lousy performance. I’ve recently been working on a project which started out mostly as some really benign (but miserably tedious) tabular data manipulation that I definitely could have pulled off with no problem in Python. Then I realized that a couple of things were going to have to happen that involved a combinatoric explosion in time complexity. I wound up mostly brute-forcing it in Julia, and the function calls I needed wound up taking a couple of minutes each. In Python they would have taken almost an hour. It wasn’t at all apparent to me that I’d be dealing with any of that kind of stuff when I started the project.

You shouldn’t have to put limits on the kinds of things you want to do because the language doesn’t cut it for some applications. Python has people trained only to use classes when they have a few hundred instances of them, and to use specialized API calls to do simple things. I don’t want to do that stuff, I want to use the super generic code in Base for everything, I don’t want to have to use a specialized API for every single thing I do. I hate reading API documentation, and I never remember it once I do. In Julia Base is your best friend. I have to use DataFrames all the time, and you know what? the only really specialized functions I have to use from that package are by and join. I’ve even stopped using DataFramesMeta and Query because I can just iterate over the DataFrames and do whatever I want without having to worry that my code won’t cut it because it’s written in the language I’m actually using. (No offense to those packages, they’re great packages, just nowhere near as vital as they’d be in Python.)

No worries, nobody is accusing you of that. Occasionally these “Julia vs Python (or R)” threads come up, and those of us who are already sold on Julia use them to vent our frustration rather than ignoring them like the mature adults we should behave like. I’m sure by now it’s clear that I have an ax to grind with Python. The very first time I used it it was miserably inadequate for the first several things I thought to try with it, and its reputation in my mind has never recovered. Julia definitely has some really significant problems right now, many of which have been mentioned here, and in the name of equity I’ll add that compile times in 0.7 are starting to get a bit worse than just a mild inconvenience. Admittedly it does get a little frustrating when everyone thinks Python is better because of the wizard behind the curtain writing all of the C code, but DON’T EVER LOOK BEHIND THE CURTAIN! :rofl:

8 Likes

Python has been around for well over 25 years for one thing, Julia, released publicly one a little over 6 years.
I think things will change as more and more CS people like me (and all sorts of people wanting to do general programming) discover Julia.

As a long time C/C++ programmer, having a REPL (which I missed since my days of Scheme programming) will help entice people, and the ability to quickly see exactly the native code produced for a method is also a big attraction. I think the final thing for some of those people will be having a good debugger, you tend to get spoiled by things like Visual Studio or XCode.

For the mid to low level programmers like me, Julia holds all the cards compared to Python.

I’m on the opposite side, but I think it might have to do with what you are exposed to first, and not as much to which one is intrisically “easier” to learn. Having learned Scheme & CLU (after Fortran, PL/I, Basic), instead of starting out with a single-dispatch OOPL (as most people probably do these days, with Python, JavaScript, C++, C#, Java, VB or Lua), multiple dispatch seems more natural to me than single dispatch.

1 Like

In my personal experience, it was a pain at first, but after not that long a while, I simply had learned enough to be able to write type-stable code (when needed) without really thinking about it.
There are also some tools like Traceur.jl, that can help figure those issues out in a fairly easy fashion.

Wonder no more (synchronicity?): 0.7 Julia now shows where isless is coming from. Btw, if you enter 1 and press ctrl-q, you’ll be right at the relevant code:

julia> max([1,2,3], 2)
ERROR: MethodError: no method matching isless(::Int64, ::Array{Int64,1})
Closest candidates are:
  isless(::Missing, ::Any) at missing.jl:62
  isless(::Real, ::AbstractFloat) at operators.jl:147
  isless(::Real, ::Real) at operators.jl:335
  ...
Stacktrace:
 [1] max(::Array{Int64,1}, ::Int64) at ./operators.jl:397
 [2] top-level scope

julia> 1  # '1' (i.e. first Stacktrace: entry) and 'ctrl-q'
#REPL jumped to 'base/operators.jl'
[snip]
"""
max(x, y) = ifelse(isless(y, x), x, y)

"""
    min(x, y, ...)
[snip]
13 Likes

I’m a biologist that got into programming through R and statistics. I’ve tried Python too, but not as extensively, and I’m not, by any means a coder or programmer o package developer. That said, I’ve found Julia more intuitive than R or Python, especially when trying to understand the code. I’m sure my lack of experience in the field doesn’t give me a lot of perspective, but when I started to go deeper into packages in R, not much made sense, I’ll run into C code and things way above my pay grade. I didn’t find that at Julia, even though I admit I still don’t completely understand how different developers accomplish some things. That’s my experience and that’s why I’ve been trying to learn Julia and preaching a little bit about it. Luckily, I don’t need to “unlearn” years of Python, something I’m sure it’s hard to achieve.

11 Likes