7 ms·
I don't have a CS background, so maybe that's how I'm missing the point here, but I don't see what is so supposed to be so special about Julia's multiple dispat
by diarrhea 6y ago
I don't have a CS background, so maybe that's how I'm missing the point here, but I don't see what is so supposed to be so special about Julia's multiple dispatch. In fact, reading more about it and knowing Python, single dispatch/polymorphism feels more natural to me. This would allow a `plot` function in Python, originally written for the float data type, to also work for float-like (quacks like a duck) data types, like `Decimal`. I struggle to see what about Julia improves on this situation or makes it conceptually different.
Lastly, the article mentions that `plot` also works for uncertainty-carrying floats, because the `Measurements` package has implemented "a simple recipe" for this case. But doesn't this mean very tight coupling? The `Measurements` author very specifically (if I understand this right) implemented a `plot` functionality. For the end user, this allows things to just work, which is great. But under the hood, it seems this depends on package authors having to be aware of all possible use cases for their library code.
- pdeffebach 6y ago> This would allow a `plot` function in Python, originally written for the float data type, to also work for float-like (quacks like a duck) data types, like `Decimal`. This might come with sacrificed performance. If you want a different implementation for a different data type to get the best performance, writing one method makes that hard. > The `Measurements` author very specifically (if I understand this right) implemented a `plot` functionality. This is a good point. But in that example, note that `Measurements` also works with all of differential equations, and they didn't implement any differential equations specific code, unlike as you pointed out with `plot`. The fact that uncertainty propagates through a differential equation solver is pretty impressive, imo.
- jschwartzi 6y agoYeah as I was reading this it occurred to me that a startling number of lab reports I wrote as an undergrad would have been much easier to do in Julia. We normally used Excel for the calculations and had to check all of our propagation of errors by hand.
- acdha 6y agoI really wish someone could get traction with a replacement for Excel with better correctness options. So many people use it because it's easy to get started with but then find themselves in situations like what you mentioned where there's a lot of manual work (or undetected mistakes) to maintain it.
- improbable22 6y agoI think we're getting there, slowly. Quite a lot of people who don't in any way think of themselves as programmers now reach for python/R/julia for tasks that would once have been done in Excel. https://github.com/fonsp/Pluto.jl https://github.com/fonsp/Pluto.jl is a super-nice way of just starting, without too much setup cost. I think it will soon be self-contained as to what packages & versions are needed, too.
- pdeffebach 6y agoJulia!
- acdha 6y agoI realize you like it but think about what we're talking about here: someone has a room full of students who have not been trained as programmers and they're working on a particular experiment, not taking a class on software development. Most of them have probably used Excel/Numbers before and if not the basic idea, especially given a template, is pretty easy to explain so you can get them up in running quickly and get back to the actual problem you're working on. Now contrast that with how much stuff you need to learn to be proficient with any programming language — and no matter how much you think your favorite one is a friendly unicorn, teaching a room full of beginners will be eye-opening for the things they get stuck on. Which editor to use? How to install it? Are you saying “$LANG” but actually using that as a shorthand for “$LANG, Git and shell tools, and the conventions for using which are common in my specialty”? How much time does it take to learn the basics of the language, how to interpret error messages, and debug things? None of that is insurmountable, of course, but the difference in learning curves is why many people end up with the Excel file which started in a hurry and is now Frankenstein's workbook which everyone is afraid to touch or share. Over a sufficient time interval, it'd be much easier to pick any decent toolchain because maintaining that level of complexity in almost any major programming language is going to be less work but unless you're starting with experienced developers the short term answer will probably favor Excel. I've seen people who've been meaning to get around to rewriting it long enough that the target language has shifted as things fall in and out of favor.
- smabie 6y agoMultiple dispatch is nice because it makes extending library (or any) code very trivial. The seamless way in which Julia libraries can be mixed and matched and used together is a testament to this. Python on the otherhand, each library is its own little world and cannot be used in novel or unexpected ways. Moreover, the unperformant nature of Python means that you must use libraries in very cookie cutter ways or else performance falls off a cliff.
- ddragon 6y agoAs the name implies, single dispatch is just a special case of multiple dispatch. Everything that can be done with single dispatch works exactly the same (arg1.f(arg2...) is just f(arg1, arg2...) in Julia), so there is no loss in expressivity. The only conceptual difference in multiple dispatch is that arg1 is not considered special, which makes sense for a scientific language as for example in 1 + 5 the operator '+' isn't really owned by the "object" 1, it's a property of the whole formula (the combination of the operator itself and all operands). And the consequence in terms of programming is exactly that it that it shifts the responsibility of handling interoperability to whoever creates a new type. For example if I create MyType and want a method SomeoneType + MyType to work, I don't need to change the '+' implementation on SomeoneType for that to work (for example making a PR on his library), I only define methods with the type I just created. Which is why people say Julia ecosystem compose a lot, the creator of SomeoneType can just focus on what he wants and possibly never even know about MyType, MyType will extend it with whatever I want without having to re-implement stuff that SomeoneType already implemented (only MyType stuff and the intersection between libraries, defined by methods that use MyType and SomeoneType), and the final user can just import all stuff he wants and have a library that looks like a monolith but is actually many smaller libraries working together this way.
- shepik 6y agoThe deal with multiple dispatch, as I understand it, is that instead of obj->somemethod, you define function named somemethod, which is defined for obj. Maybe some other code calls it. You can then define somemethod for other data types, without touching the original definition, and that makes your new definition available to the other code that used the original somemethod. It is a unique feature of Julia (at least unique in a sense that it is absent from mainstream languages)
- jabl 6y agoThe thing that distinguishes multiple dispatch from single is that you can dispatch based on the types of all arguments to the method, not just one. E.g. you can define function somemethod(x::Int, y::Int) function somemethod(x::Int, y::Float64) function somemethod(x::Float64, y::Float64) Multiple dispatch is available at least in Common LISP, though I guess that's not considered particularly mainstream.
- DNF2 6y agoAs far as I know, multiple dispatch is optional i clisp. It also exists in R, but again, is optional (and slow), and is therefore mostly unused, which limits its usefulness, making it less used, etc. etc. In Julia, it is default, so everything participates in multiple dispatch. It completely pervades the language, which is what makes it so useful.
- leephillips 6y agoIt is also available in Perl6, but there, as in CL, it is opt-in, and might slow things down.
- shepik 6y agoRight. I (incorrectly) assumed that "multiple" meant multiple versions for different input types, not necessarily multiple arguments.
- badsectoracula 6y agoIsn't this the same as function overloading in some programming languages?
- StefanKarpinski 6y agoThe core problem with class-based object orientation is that methods go inside of the type instead of being added externally. That means everyone has to agree on what methods can be called on a class or they have to subtype it, which sounds harmless, but is actually a big problem when what you really wanted to do was just define a new method for an existing type. My best attempt at explaining: https://www.youtube.com/watch?v=kc9HwsxE1OY https://www.youtube.com/watch?v=kc9HwsxE1OY There's also the issue that one sometimes needs to specialize generic operations in generic algorithms on something other than the receiver—sometimes even on more than one of the arguments. Single dispatch forces you to use something slow and awkward like double dispatch in cases like this. And that's assuming the person who wrote the generic code anticipates the need for specialization! If they don't allow for it, then you're just stuck. With multiple dispatch, you can just define the method you need the specialization for and you're done.
- leephillips 6y agoA couple of the other replies might have answered this for you already. You are correct that the recipe is specific to the Plots package. But consider: once written, it works not only for that specific plot function, but many others in the package as well, for example scatter. Also, I have written these recipes for my own data types, and they are incredibly easy to create. The recipe informs the functions in Plots how to handle your datatpye, so you can just pass it in as an argument. The thing is that I’ve never even looked at the code in the Plots package. With Julia you can use functions on combinations of your own custom datatypes to do new things, without looking at the code for the functions. Often nothing like the Plots recipes are required; but here the recipe lets you specify how you want your datatype to be visualized.
- gnufx 6y agoApart from CS and how software construction works with these things in practice, I reckon multiple dispatch is natural. At least it is to someone with a physics background, which is the context in which I encountered it long ago. I'm used to thinking essentially functionally and in terms of operation->arguments/objects (or verb->subjects), not something with the order and asymmetry of, say, object.operation(object). I wouldn't expect an operation to be tied just to one of the operands. I've seen the result of people trying to explain to scientists, say, Java-like "OO" as if it was somehow mirroring the sort of things they work on.
- munificent 6y ago> This would allow a `plot` function in Python, originally written for the float data type, to also work for float-like (quacks like a duck) data types, like `Decimal`. So let's say you do that. You define your own new number-like type, say Complex. You pass that in to plot(n). Somewhere in the body of plot(), though, it turns out there's some code like: # Flip to put origin at bottom left. window_height = 400 y = window_height - n So now plot() tries to invoke "-" with an int on the left and your complex number on the right. It passes your complex number to the int class's minus operator, which has no idea about your type and barfs. Python has a hacky workaround for this specific case where the right operand can implement __rsub__(), but that hacky workaround exists specifically because Python doesn't have multiple dispatch. If it supported multiple dispatch natively, you'd just define an operator - that took a number on the left and a complex on the right, plot() would call it, and you'd be good.
- leephillips 6y agoWow, nice example. Made possible also because arithmetic operators in Julia are functions, and you can extend them to work on any data types. (Operators like "+" have hundreds of methods.)
- ChrisRackauckas 6y agoPlot recipes are a really good fundamental example of composability in the Julia ecosystem. Extending a plotting library cannot be a function because plotting functions don't compose. Want to support plotting quaternions in matplotlib? You'd write a `plotquaternion` function. Then the ODE solver makes a `plotode` function for the output object of its ODE solver. Now let's say you got ODEs solving on quaternions... what about plotting? Well you have to modify `plotode` to call `plotquaternion` or modify `plotquaternion` to call `plotode`, and this is how you get monorepos and the big functions we all know. Plot recipes are different. The Plots.jl system calls the type recipe function recursively on the plotting data `X` until it sees a set of primitives that it knows. Libraries define dispatches to this function to denote how data types should transform to something more primitives. Quaternion numbers become four independent series of numbers (and add keyword arguments for doing things like modulus). The ODE solver library writes a recipe that say, if you try and plot an ODE, transform it into arrays of time series. Now plot on a quaternion ODE solution recurses into 4x time series of the solution, which is the plot you'd want to have. This is a feature I use all of the time: I don't generally do more than just `plot(sol)` since recursive recipes generally give me the plot I want (or else I open an issue because someone is missing a recipe).
- socialdemocrat 6y agoI wrote two articles which may clarify this better. One is about creating custom temperature units in Julia and Python. It shows how multiple dispatch gives an advantage over single dispatch: https://medium.com/@Jernfrost/defining-custom-units-in-julia-and-python-513c34a4c971 https://medium.com/@Jernfrost/defining-custom-units-in-julia... This story is more like a general intro to Julia, but it has an example with Knights, Pikeman and Archers fighting each other (sort of rock, paper, scissors game), which also shows the utility of multiple dispatch. https://levelup.gitconnected.com/knights-pikemen-archers-and-multiple-dispatch-69aaee2c4141 https://levelup.gitconnected.com/knights-pikemen-archers-and... But to give a quick idea here. Imagine writing functions for intersecting two geometric shapes. The algorithm for intersecting a circle and square is entirely different from intersecting a polygon and a line segment. The specific algorithm needed will depend on BOTH shapes not just one. Python can only dispatch on one of the shapes, not both. So in Julia I could write a different function implementation like this: intersect(c::Circle, r::Rectangle) intersect(c1::Circle, c2::Circle) intersect(r1::Rectangle, r2::Rectangle) and so on.
- musingsole 6y agoI appreciate your first article demonstrating the differences between Python's single dispatch and Julia's multiple dispatch, but your python example suffers from a lack of a child-aware parent class, Temperature, that could resolve the complaints raised. You're building inherently coupled classes in a decoupled way and complaining that they don't mix well.
- musingsole 6y agoAs the other answers note, multiple dispatch is largely a performance improvement. When writing Python, performance has usually been sidelined as a priority in the first place (within some constraints). Personally, I hate this presentation. Multiple dispatch (to me) is cognitively heavier and not what I would default to. If it's a performance gain and I need performance, then sure. But too often people hold it up as a virtue because the need for speed is assumed.
- amkkma 6y agoWhat? I used to write python, and to me, MD is first and foremost a conceptual improvement. Makes writing code so much sweeter, more expressive and sensical. It also heavily improves composability. It's LESS performant if not done carefully. Certainly FastAI, Matt rocklin etc didn't reimplement a subset in python just to get slower code See https://youtu.be/kc9HwsxE1OY https://youtu.be/kc9HwsxE1OY
- DNF2 6y agoI agree, the performance is a very nice bonus, but it is primarily about expressiveness, composability and natural simplicity. It just seems profoundly un-natural and arbitrary to limit dispatch to only the first argument.