It looks really promising, like “the way things were always supposed to be”, but I haven’t yet developed a full and intuitive understanding of what it means.
It looks really promising, like “the way things were always supposed to be”, but I haven’t yet developed a full and intuitive understanding of what it means.
In my mind it also removes a lot of cases where I need major restructuring and and refactoring in typical OOP languages. Getting type hierarchies and code organization wrong is so much easier with OOP and much harder to de-tangle.
Not always easy to explain with examples. Once you used MD for a while and try SD again you really start noticing how clunky SD makes code writing.
If you're coming from a functional language, the main difference is that Julia will compile specialized versions of functions for your types, and makes it a lot easier to write runtime efficient and generic code.
For a simple example of this in action, consider the following
julia> a = 1//3 # a is the rational number 1/3
1//3
julia> b = 2+3im # b is a gausian integer (complex number with integer coefficients)
2 + 3im
julia> a+b # even though these types don't know about each other, appropriate methods get called to get a complex rational result.
7//3 + 3//1*im
This might seem really basic, but you'll be hard pressed to make a system like this in another language without hard coding a list of dispatches manually.
If I wanted to use eg Euler angles or modified Rodriguez vectors or some other representation of rotation, the identical code pattern would work.
Any language with semi-decent support for generic programming (via traits, type classes, overloading, what have you) should be able to do the above.
Well, Julia has better than semi decent support for generics, since every function is by definition a generic.
MD can be useful for static languages of course, but it comes up significantly less often and static MD is simply overloading/ad-hoc polymorphism.
It does so many things very right and always from first principles, not ad hoc (ad hacks).
some random examples that I love
sum(xs...) = reduce(+, xs)
julia > (6ft + 1km) * 1km/s 1002 m s⁻¹
julia> 'a' in "abc" true
180° + π == 2π
map(x -> 2x, [2,4,6,8]) == [2,4,6,8].*2
julia> ⊕(x, y) = x+y
julia> 1⊕2
3
∑(xs...)=fold(xs,+)
julia> ∑(2,4,6,8) 20
∑(xs)=fold(xs,+)
julia> ∑([2 4 6 8]) 20
Firstly I like the aesthetic and implications of f(x, y, z) over x.f(y, z). I like that f is its own thing and not a property of x.
Secondly, it's really nice to be able to reach however far down the callstack you need to go to patch some function "owned" by someone else to act correctly or more efficiently with whatever your type is. You can get correct code most of the time with single dispatch and well-thought-out interfaces, but getting interfaces right in advance is really tricky and requires coordination with other users of the interface whereas multiple dispatch can often work well without much coordination and can also handle cases where you want the implementation to vary dramatically based on the type (the OneHotVector in Karpinski's "Unreasonable effectiveness of multiple dispatch" talk is an example of this).