Not trying to spin up any controversy… but do we have a list about things that are better in Julia than Python and vice versa as of today? To have a productive discussion, I would think such list should contain items that are fairly clear (eg speed) rather than those that are highly subjective (eg multiple dispatch vs object oriented).
If you are limitting it to things that are as objective as speed,
and less objective then multiple dispatch vs OO.
Then I think you might have hit the empty set of things to talk about.
Since Multiple Dispatch vs OO is more objective than speed.
People constantly argue about benchmarks.
Is it fair to use @inbounds
, is it fair to use multi-threading?
Should tail-recursion be not used.
(Code size benchmarks also have similar problems)
Where as Multiple Dispatch vs OO is pretty clear.
Multiple Dispatch is outright more powerful than single dispatch (which is common in OO).
Though the associated polymorphism related discussions (inheritance, composition, traits, etc) much more debatable than that.
When it comes to language features it is hard find any that are more objective,
than Julia has multiple dispatch, python has up-to single dispatch.
Julia has macros, python does not have macros, but are macros even good – debatable.
Like if you are just looking for benchmarks go find benchmarks?
Don’t forget this handy section of the manual!
What usually happens in this context is that people who care enough invest effort into making things fast, making these comparisons reflect the skill, dedication, and interest of the members of the respective communities, in addition to general the “speed” of the language (which is also not clearly defined).
In Julia is that this process is accessible to users of the language: after some initial investment, it is relatively easy to discover and fix speed issues. But this is a “soft” feature, harder to quantify.
Generally, I would stay away from “Julia vs X” comparisons, and just emphasize what Julia has to offer. Eg the advantages of parametric multimethods will be relatively obscure for those who have not run into the problems that they fix, but will be immediately apparent to those who have.
In Python if you have an object x, dir(x) will return a list of all methods that apply to x. I’ve found no similar ability in Julia with generic functions.
-Tom
Because in Julia it’s not a small or finite set.
Also there’s methodswith
:
julia> methodswith(Dict)
29-element Array{Method,1}:
convert(::Type{Dict{K,V}}, d::Dict{K,V}) where {K, V} in Base at dict.jl:208
copy(d::Dict) in Base at dict.jl:134
delete!(h::Dict, key) in Base at dict.jl:558
done(t::Dict, i) in Base at dict.jl:578
empty!(h::Dict{K,V}) where {K, V} in Base at dict.jl:304
get(h::Dict{K,V}, key, default) where {K, V} in Base at dict.jl:478
get(default::Union{Function, Type}, h::Dict{K,V}, key) where {K, V} in Base at dict.jl:483
get!(h::Dict{K,V}, key0, default) where {K, V} in Base at dict.jl:434
get!(default::Union{Function, Type}, h::Dict{K,V}, key::K) where {K, V} in Base at dict.jl:444
get!(default::Union{Function, Type}, h::Dict{K,V}, key0) where {K, V} in Base at dict.jl:436
getindex(h::Dict{K,V}, key) where {K, V} in Base at dict.jl:473
getkey(h::Dict{K,V}, key, default) where {K, V} in Base at dict.jl:527
haskey(h::Dict, key) in Base at dict.jl:505
isempty(t::Dict) in Base at dict.jl:581
launch(manager::Base.Distributed.SSHManager, params::Dict, launched::Array, launch_ntfy::Condition) in Base.Distributed at distributed\managers.jl:121
launch(manager::Base.Distributed.LocalManager, params::Dict, launched::Array, c::Condition) in Base.Distributed at distributed\managers.jl:317
length(t::Dict) in Base at dict.jl:582
next(t::Dict{K,V}, i) where {K, V} in Base at dict.jl:579
pop!(h::Dict, key) in Base at dict.jl:538
pop!(h::Dict, key, default) in Base at dict.jl:543
rand(r::AbstractRNG, t::Dict) in Base.Random at random.jl:374
rand(t::Dict) in Base.Random at random.jl:381
serialize(s::AbstractSerializer, d::Dict) in Base.Serializer at serialize.jl:337
setindex!(h::Dict{K,V}, v0, key::K) where {K, V} in Base at dict.jl:420
setindex!(h::Dict{K,V}, v0, key0) where {K, V} in Base at dict.jl:412
similar(d::Dict{K,V}) where {K, V} in Base at dict.jl:192
similar(d::Dict, ::Type{Pair{K,V}}) where {K, V} in Base at dict.jl:193
sizehint!(d::Dict, newsz) in Base at dict.jl:274
start(t::Dict) in Base at dict.jl:574
I figured someone would point that out. But even just listing methods whose first argument is typeof(x) would be useful.
Yeah, but to get the true answer you’d have to merge that with every method for abstract supertypes. Not hard, but the list will be huge and uninformative to say the least.
Isn’t that just what methodswith(T, true)
does? From the ?methodswith
doc:
If optional showparents is true, also return arguments with a parent type of typ, excluding type Any.
Example:
julia> methodswith(Dict, true)
62-element Array{Method,1}:
==(l::Associative, r::Associative) in Base at associative.jl:338
convert(::Type{Dict{K,V}}, d::Dict{K,V}) where {K, V} in Base at dict.jl:208
convert(::Type{Dict{K,V}}, d::Associative) where {K, V} in Base at dict.jl:197
...
I do agree that it can be very useful when exploring a new library in Python to create and object and then do obj.<tab>
to get a sense of what I can do with that object. Of course, even in Python that list is still just a subset of what you can actually do, as it doesn’t include useful things like:
- build-in functions like
enumerate()
- operators you might apply to an object
- any generic functions that could work with that object
- protocols like iteration, indexing, etc.
Woah.
Right??!?
Fair enough. From talking to a number of people who want to migrate from a different language e.g. Matlab or SAS, the most common question is why one chooses Julia over Python given the vast Python libraries available. Then, the common response is that Julia solves the two language problem as it is fast. Then, the response is that does speed even matter for the use case. So the conversation pretty much circle arounds speed. Language features don’t play well in such discussions either as they’re so debatable as you mentioned above.
How about having a list that goes like this. Feel free to add or yay/nay anything below:
Python has advantages in these areas
- Better development tools e.g. debugger
- Large talent pool
- Natively supported by cloud vendors e.g. AWS Lambda
- Natively supported by apache spark
Julia has advantages in these areas
- Easy to make things fast without much effort
- Reduced operating cost due to more efficient use of hardware (related to #1)
- Ability to build domain specific languages using macros
Ok I feel these things are still debatable but W/E
Julia advantages:
Nicer syntrax for matrix operations.
-
A*B
vsA.dot(B)
-
A'
vsA.T
-
A[:, end÷2]
vsA[:, len(A)//2]
-
[A; B]
vsnp.stack([A, B], 2)
-
[A B]
vsnp.stack([A, B], 1)
-
[A B; C]
vsnp.block([A,B], [C])
-
foo.(A)
vsnp.vectorize(foo)(A)
Also the ability to not always broadcast every operation, so that one gets errors when one screws up.
You can use them from Julia using PyCall
While python has a no doubt hundreds of times as many academic users as Julia (maybe even thousands).
The academic users are like <0.0001% of all python users.
Where as they are >90% of all Julia users.
Which means the julia community (and ecosystem) is a really vibrant academic place,
You can find a lot of discussion that is relevant in this thread: “Julia motivation: why weren’t Numpy, Scipy, Numba, good enough?”
Many points are brought up. For me, the focus on first class numerical programming support is among the most important. Numpy’s syntax is pretty awkward compared to Julia.
I have really come to love multiple dispatch, which relieves me of almost all the tedious input parsing that you encounter in Python (and even much more so in Matlab!) I would estimate that about 25% of all coding time I’ve spent in Matlab was on input parsing, or figuring out how to efficiently branch my code based on the type of a variable.
Lightweight or zero-cost abstractions are great! You can choose an appropriate level of abstraction without sacrificing speed, and get very elegant and readable code.
EDIT: Oh, and of the remaining 75% of programming time, I’d say most of it was spent figuring out insane code vectorization tricks, to help performance. This is pretty much the same in Numpy.
I don’t have the numbers, but my understanding is that while many people use Python, Julia has a comparatively (in a relative sense) large number of active contributors to the language. To contribute to Julia, you just need to know Julia.
IMO this is an extremely important point, both for the ecosystem and the management of expectations. Julia attracts people who need to implement something and want to do it in a generic and efficient manner. Those who are using another language just for an existing toolkit or library, mostly writing “scripts”, may benefit little from Julia at this point, especially if their key library is missing or WIP.
Depends. If you want to contribute to e.g. code optimization some C, LLVM IR and internals and some background on femto-lisp would be needed.