6 ms·
The missing harm of manual dispatch in Julia
- pdeffebach 6y agoThis is a good feature! Sometimes, you want to use `if` `else` based on type information, say if your function is very large and the different behavior based off of type is only a small piece of the process you want to convey. It's great to have the flexibility.
- doublesCs 6y ago> This is a good feature! Sometimes, you want to use `if` `else` based on type information, say if your function is very large and the different behavior based off of type is only a small piece of the process you want to convey. Super interesting point, thank you.
- compressedgas 6y agoThis only shows that it can do method type specialization to get rid of type dispatch. Can you add a new multimethod clause to an existing if-then-else type dispatch method? For example add: foo(x::Baz) = x.foo Or is harm still done because the method is not open for extension when written like that?
- pdeffebach 6y agoYou can't edit a function like that. If you add a new function definitoin for foo(x::Baz) then you will never enter the method that has those if else statements. This is the benefit of multiple dispatch. You can't add more if else statements inside a method that is already written but you can add new methods.
- stabbles 6y agoManual dispatch can be an antipattern hindering composability though. If package A does: function foo(x) # some lines of code y = x isa Int ? 2.0 : 3x # some other lines that do things with y end Then package B would have to define foo(x::MyType), copy the contents from package A, change the `y = ...` bit, and make sure the rest stays in sync with package A. If instead package A did this: foo_magic(x::Int) = 2.0 foo_magic(x) = 3x function foo(x) # some lines of code y = foo_stuff(x) # some other lines that do things with y end Your package B could just add an extra definition of foo_magic(x::MyType) instead.
- nur0n 6y agoI love how easy it is to view the machine code for a function. Julia actually ships with a handful of these introspection macros: https://docs.julialang.org/en/v1/devdocs/reflection/#Intermediate-and-compiled-representations https://docs.julialang.org/en/v1/devdocs/reflection/#Interme.... They are invaluable when it comes to optimization.
- stabbles 6y agoIndeed, inspecting typed code, lowered code, llvm ir, and native code from the REPL is great. Combine that with @benchmark for microbenchmarking and it's amazing. Note that the 'manual dispatch' is optimized out in a very early stage: julia> @code_typed foo(1) CodeInfo( 1 ─ return 2 ) => Int64 So, no need to look at assembly here.
- g0wda 6y agoProf. Alan Edelman gave a nice lecture about this a couple of days ago https://www.youtube.com/watch?v=IuOXXQR7dAo https://www.youtube.com/watch?v=IuOXXQR7dAo
- doublesCs 6y agoI keep saying that Julia is the future. No more tinkering with Cython and other hacks.
- qaq 6y agoHave to agree, just recently started playing with it and was blown away. If web side gets a bit more polish it will become a killer lang for web development.
- amkkma 6y agohttps://genieframework.com/ https://genieframework.com/ (A Django like MVC framework, with templating and a julia -> JS compiler for the frontend) https://www.youtube.com/watch?v=xPUOCQ2SJF0&list=PLP8iPy9hna6Tl2UHTrm4jnIYrLkIcAROR&index=88&t=477s https://www.youtube.com/watch?v=xPUOCQ2SJF0&list=PLP8iPy9hna... (JuliaCon 2020 | Write a WebApp in Julia with Dashboards.jl |) youtube.com/watch?v=uLhXgt_gKJc&list=PLP8iPy9hna6Tl2UHTrm4jnIYrLkIcAROR&index=10&t=11428s (JuliaCon 2020 | Building Microservices and Applications in Julia) https://www.youtube.com/watch?v=8sciqIMXBng&list=PLP8iPy9hna6Tl2UHTrm4jnIYrLkIcAROR&index=158&t=87s https://www.youtube.com/watch?v=8sciqIMXBng&list=PLP8iPy9hna... (JuliaCon 2020 | Interactive data dashboards with Julia and Stipple | Adrian Salceanu)
- qaq 6y agoThere are def. projects that show promise.
- leephillips 6y ago“a julia -> JS compiler for the frontend” Really? Where? I’d love to know about that.
- ChrisRackauckas 6y agoHere's an instance of it: https://keno.github.io/julia-wasm/website/repl.htm https://keno.github.io/julia-wasm/website/repl.htm and the repo: https://github.com/Keno/julia-wasm https://github.com/Keno/julia-wasm
- marcuspolo 6y agoI am not a Julia user, can the compiler optimize away the run-time type checking when `foo`'s argument is not easily known at compile time? e.g., foo(function_which_returns_dynamic_type())
- stabbles 6y agoYes, this is another reason to prefer julia's dispatch over manual dispatch. In this case the cost of the dynamic type being returned is just a _single_ dynamic dispatch. Dynamic dispach means that the correct function foo will be looked up in julia's method table. But when this foo is called, all types are inferred, and it will run optimized for these types. This is called a function barrier. A function barrier can be used as an optimization too: if you have a large function where one of the local variables has a type that is abstract / not concrete / not properly inferred by the compiler (e.g. `::Union{A,B,C}`, `::AbstractVector`, `::Any`), it can be beneficial to split the function into two functions, such that the latter function can be optimized for concrete types, and the former function only has the overhead of a single dynamic dispatch.
- socialdemocrat 6y agoI think you may have some misconceptions. Julia is not compiled ahead of time. A function does not spring into existence until the definition of the function is executed. Same applies to a struct definition. In a statically typed language you might write a function that takes an integer like this `foo(x::Int)` but in Julia it is completely possible to replace the `Int` with an expression that returns a type object. Meaning you actually run code at runtime to figure out what the defined function should actually operate on. So there is nothing known at compile time, because everything happens at runtime. However when a function is called for the first time, then the JIT compiler will compile it and store the result. But it will store different compiled versions of the same function depending on the type of the argument it was called with. If you call the same function later with the same type of argument, it will reuse a previously compiled version. If this is all very unclear. You could look at an article I wrote contrasting static typing with how typing works in Julia: https://medium.com/@Jernfrost/types-in-c-c-and-julia-ce0fcbe0dec6 https://medium.com/@Jernfrost/types-in-c-c-and-julia-ce0fcbe...
- ddragon 6y agoThis reminds me of these slides on the Julia compiler and Zygote [1] that really impressed me at the time. Not only the compiler is incredibly smart, it also gives the programmer to a lot of tools to talk with it (the introspection macros, IR Tools, macros on AST, macros on IR - generated functions). And maybe a little related, while traits are not a feature on the language, you can use this kind of compile-time optimizations to implement trait dispatch that the compiler will completely erase from the generated code, the so called holy traits [2]. [1] https://docs.google.com/presentation/d/1IiBLVU5Pj-48vzEMnuYEr9WQy9u2oi6Yk_8F3sgGkvQ/preview#slide=id.p https://docs.google.com/presentation/d/1IiBLVU5Pj-48vzEMnuYE... [2] https://invenia.github.io/blog/2019/11/06/julialang-features-part-2/ https://invenia.github.io/blog/2019/11/06/julialang-features...
- carabiner 6y agoMissing harm considered harmful.