Is Julia's way of OOP superior to C++/Python? Why Julia doesn't use class-based OOP?

One of my personally favorite ways to demonstrate how something conceptually straightforward is difficult in Python is to compare

julia> 1//10 * im + 2//10 * im
0//1 + 3//10*im

and

>>> from fractions import Fraction
>>> Fraction(10, 100) + Fraction(20, 100)
Fraction(3, 10)
>>> Fraction(1, 10) * 1j + Fraction(2, 10) * 1j
0.30000000000000004j

The problem happens when you do Fraction(1, 10) * 1j , but I like to show the floating point “error” for dramatic effect, since that’s the real-world consequence of trying to do rational and complex arithmetic with <class 'fractions.Fraction'> and <class 'complex'>. As far as I know, you cannot. They are even both in Python’s standard library, and designed with some awareness of each other, but the result is still subpar.

I aimed to go into the details of the complex-rational example with this presentation I gave to my lab.

Specifically, I call out this code comment:

https://github.com/python/cpython/blob/dc7a50d73a3d16918529669ff7b8783c08cff090/Lib/fractions.py#L276-L355

This isn’t even linear algebra. It’s just complex numbers and rational numbers, and already you see it’s necessary for Python to “Greenspun” something that amounts to multiple dispatch. But not really, because it’s closed off in at least two important ways:

  • it only works for two arguments and for specific dunder procedures
  • the switching logic over types is not extensible without modifying the source (one direction of the already-mentioned expression problem). Take stock of all the isinstance conditions…

By the way, I just tried the notebook in mybinder.org, and it seems to work just fine.

20 Likes