1. 35
  1.  

  2. 17

    Your site looks beautiful :-)

    1. 6

      I totally agree. Everything is so crisp. The pokemon type tags were exactly right.

      1. 7

        Thanks! I did the CSS myself (it was very painful). I did the diagrams in Adobe Illustrator

    2. 5

      It looks like Julia never added explicit interfaces. That’s a bummer. I know there was some discussion years ago, but I moved off of projects where it made sense as a language choice, so I lost track. I always felt that making interfaces explicit would help with documentation (at a minimum) since, at least at the time, it was common to see an informal interface referred to in documentation, but never fully documented itself. This made it trial-and-error to implement.

      1. 6

        With dynamic dispatch/typing, you really don’t need an explicit language construct for interfaces. In a language like Java, it’s completely dependent on the user to define that relationship. When you have a function like push!(collection::AbstractArray, item::T) your “inferface” is a loose contract. That being said, libraries like Traits.jl / WhereTraits.jl implement a macro to assist in any strict interfaces.

        1. 5

          Yeah, I understand they’re not necessary, but I prefer them because they force a kind of documentation. Otherwise there’s no way for me to know that a particular type implements an interface without inspecting all its method implementations.

          1. 2

            Absolutely, in an ideal world you’re within slapping distance of people who don’t document their code. :)

      2. 4

        This makes a good case! But the criticism I’ve seen of multi-dispatch in other languages (CL, I think) is that the rules for which function to invoke can become complex and unintuitive. In Julia it looks like a more-specific parameter type beats a less-specific one, but what happens when there are two candidate functions, where one is more specific in param 1 but the other is more specific in parameters 2?

        1. 9

          In that case you’ll actually also get a MethodError since it cannot be resolved to a concrete method. Further reading: https://docs.julialang.org/en/v1/manual/methods/#man-ambiguities

          1. 2

            What happens if the two candidate functions are defined in two different libraries/modules? Does importing both mean I’ll get errors calling those functions, unless I write my own specialization covering the types I’m using? Or are the two functions in different namespaces so I can disambiguate which one I want? (Sorry if this is super basic, but I know nothing about Julia.)

            1. 1

              Functions belong to a specific module, so just sharing a name isn’t sufficient to cause any problems with method resolution.

              But, yeah any module can define methods on any function and you can definitely cause method ambiguity errors by defining a bad method.

              Method ambiguity errors are thrown when you try to call a function and Julia can’t determine which method to call.

              In practice, this is rarely a problem if the packages you use avoid what we call “type piracy”. You do that by defining methods for a function only when you own either the function or at least one of the types of the parameters.

              I’ve used Julia for several years and I’ve never encountered a method ambiguity error except when it was my fault.

              1. 1

                Good question, that’s actually something I haven’t come across so far. It’s definitely possible to extend a function from a different module but you have to be explicit about what function you’re extending (i.e. you have to write Base.+(Mytype, Mytype) = ...). So usually it’s pretty clear what function you’re extending and I think it’s less common to use foreign types in function definitions. But I suppose it is possible that you can get a MethodError by importing a module, but I also don’t know to much about it.

          2. 4

            This is a blast from the past — I remember multiple dispatch being a hot topic in the 80s-90s and proponents struggling to come up with a comprehensible but short example. Of course the value of multiple dispatch only shows up when your system is too complex to give a short example!

            Back then it tended to get all mixed up with object-oriented politics. People would try to say “self-based dispatch” is just a special case of multiple dispatch, but it’s hard to reconcile multiple dispatch with the message-passing paradigm inherent to object orientation. It makes much more sense to say it’s a functional paradigm, as CLOS and Julia do. Nowadays functions are trendy again and I hope you won’t get nearly as much backlash from OO adherents.

            Minor nit: the article says without multiple dispatch you’d need an “exhaustive” nested switch, but wouldn’t you just need to manually do the same 30 tests the type system is doing in Julia?

            1. 1

              You might like a talk called “The unreasonable effectiveness of multiple dispatch”, which has lots more motivation for this concept.

              Re: nit,

              Yeah, the switch or method selection logic has to happen somewhere, but if you’re using multiple dispatch you don’t need to write it yourself and you get nice properties that a manually written switch doesn’t have: like open classes (in this blog, the flying Pokémon are added later without any changes required to the other code) and good method resolution logic for more complex cases.

            2. 3

              Thanks for the post, I was looking forward to it since you announced it yesterday. A minor note: the last paragraph/sentence it missing a word.

              I’m still trying to somehow use Julia but find myself resorting to python anyways due to the availability of libraries, unfortunately.

              1. 1

                Fixed! Thanks, I’ll fix that in a bit! I just use Julia for personal projects, and honestly if I can’t find a library for what I want to do, I’ll usually write that functionality from scratch as a bit of an exercise.

              2. 2

                Minor typo. You have eff(atk::Electric, def::Grass) = NO_EFFECT. You should have eff(atk::Electric, def::Ground) = NO_EFFECT.

                Overall, good article. I am trying to use Julia more and more (instead of python) since it seems to me to be an extremely versatile language, and with good support for mathematics.

                1. 1

                  Fixed! oops! thanks for catching that!

                2. 1
                  # Implement the self-to-self case
                  eff(atk::Flying, def::Flying) = NOT_VERY_EFFECTIVE
                  

                  Isn’t this line unnecessary due to the following?

                  eff(atk::T, def::T) where {T <: PokéType} = NOT_VERY_EFFECTIVE
                  
                  1. 2

                    Ah! good catch. It’s actually a typo. Flying cannot attack flying according to the type chart.

                  2. 1

                    Everybody in this thread learning what you can do with Julia and wanting to learn what the current frontier with it is should note that Juliacon starts the 28th (workshops are currently ongoing until then): https://juliacon.org/2021/

                    1. 1

                      I love Julia as a language, and I need to revisit it sometime, but when I tried to do some practical work in it a year ago I found the performance problems too limiting.

                      1. 1

                        Performance problems of what sort? For what kind of work?

                        1. 1

                          Takes a long time for a script to start up. In one of my simple scripts it took a minute or so just to compile before every run

                          1. 1

                            Yeah that’s a lot of startup time. I believe it’s possible to precompile (which is true of Python as well)

                            1. 1

                              Sort of. I’ve had some long threads about it on the forums. You can do something like precompile, but it’s not as easy as with something that produces a binary. You can also turn most of the compiling off, which helps but with a runtime performance penalty. It’s something the team is actively interested in improving, though, it’s just probably not top of the pile because the original target market was data science where startup is rarely an issue.

                              1. 2

                                Julia 1.6 and up have significantly better startup time and precompilation is now done in parallel at the time you add packages, so the perceived and wall-clock wait time is much smaller.

                                Worth checking out!

                                Startup time for individual scripts can still often be too slow, but it has become better and it is much easier to define useful package-level precompilation.

                                1. 1

                                  Oh that’s a little disappointing to hear.