Is Julia 2.0 needed?

C# has a nice solution for this with extension methods. They were specifically introduced for the kind of piping that LINQ requires.

6 Likes

You’ll probably find Jeff’s talk at CERN yesterday interesting — it’s explicitly about the ongoing work in making Julia attractive for C++ developers and use-cases. None of the things he presents need a breaking 2.0, but are really pointed at the same core motivation here.

21 Likes

I hope the information from that talk ends up in a blog post on Julia lang’s website as well. I find it a bit disheartening that so many great projects don’t get more recognition.

2 Likes

It’s very manageable when the type or function isn’t part of a large code base (like Base), isn’t extended by many (or any) packages, or the search is restricted to particular modules. Multiple dispatch’s composability would increase the size of this list, but I’ll clarify that it’s not so much about list size as what gets to be in that list.

Member completion in OOP languages shows methods belonging to a particular class. You’re not seeing any external functions designed to work on the class’s instances, even functions in the same package as the class definition. We couldn’t use the object.method() syntax to call those anyway, we would read the documentation and use what we know, maybe with a little help of member completion for a module.

Reflection like methodswith to find the “most relevant methods” is not at all the same thing. It can easily cover many more methods that aren’t bounded to a type, so it’s much more important to filter by module like you said. A much smarter UI than typical member completion’s is necessary to save us clicks compared to manual methodswith and to make this usable.

Also consider that methodswith excludes ::Any arguments for the given type even at its most comprehensive; while this rules out the obviously unintended methods for a freshly defined type, it also ignores any following unannotated methods we did intend for our types. Say I define a type X and implement Base.iterate; methodswith would find this. Then I make a bunch of functions to work on iterables, including and especially X; methodswith can’t find those. A version of methodswith that includes ::Any arguments in the same module isn’t a straightforward solution because it’ll wrongly catch all the functions I didn’t intend for X.

Designating and finding relevant methods is just not as straightforward as showing member methods.

4 Likes

Oh okay yeah I see what you are saying. Yeah I think reflection like methodswith that is filtered properly could be even more powerful like you mention, but yeah I think we need the syntax like Pipe.jl or Chain.jl in julia base or at least just pick one to try and use in lsp?

I think if the tooling was there, more people would maybe have the unannotated method as well as the specific method that just points to the unannotated when that’s the case (And in the case of type piracy, maybe we can have a @annotated function foo(s::SpecificType) that sort of tricks the lsp but doesn’t actually create type piracy). I wouldn’t mind the incomplete list (like you said even OOP has incomplete lists of methods), but as a developer, you could make a package that highlights the methods to use for a type if the tooling was there I think. This would be a great!

Whether on the developer or the user side, we shouldn’t be forced to use particular syntax to just help answer the question “what can I do with an instance of this type?” Good documentation tells us a package’s use of a type without imposing arbitrary coding styles; any worthwhile tool has to work better and make us freer, if anything. It’s been said member completion is “too OOP” for us, but this is actually just as applicable to OOP. When people want to find out what they can do with a NumPy array, they likely care about their imported SciPy submodules, not ndarray’s limited member methods. Member method call syntax doesn’t seem like the way forward.

Couple more notes on this: 1) methodswith does filter via names when the search is restricted to a module, which we may not necessarily want, 2) v1.11’s public keyword can serve as a filter for public vs internal names. Whatever this tool is, I imagine it would have a lot more settings for us to toggle.

Probably should split this code completion subthread, it got fairly independent of the Julia 2.0 topic.

1 Like

I probably spend 50% of my time writing Julia code, and 25% TypeScript and Rust each these days. I’m a much better Julia programmer than TypeScript or Rust. But in my own subjective assessment, I’m way more productive when I’m writing TypeScript or Rust, and it is primarily due to the . method completion support in IDEs that these languages have. At the end of the day, it is one of those small things that just really, really has a huge impact on how one writes code…

22 Likes

Then why not just merge Feat/methodswith dot completion by xgdgsc · Pull Request #3240 · julia-vscode/julia-vscode (github.com) ?

3 Likes

Setting a time limit for this thread, which is starting to become a generic thread on how Julia can become better / more popular. Time limits for unfocused discourse threads?

14 Likes

Mojo looks interesting.

I don’t disagree Julia code looks really nice.
with OOP you would fix the set of functions that operate on the data model of Vector2D; functions are tied to the data model. If you want to export new behavior for someone else’s data model, you need to export your own subtype of Vector2D, or keep your new behaviors private.

If the original author intended for Vector2D to be populated by behaviors implemented by others, he could write the interfaces and factory methods in the original design, so that expectations are documented and predictable, and assisted by the compiler.

Multiple dispatch favors exporting functions rather than data. It’s true in some cases the algorithm is more generic than the data model. But even such generic algorithms have expectations about the data; so they should still be specified using interfaces.

1 Like

In that wording, no. OOP languages generally have functions outside of classes; some have function overloading to provide a compile-time polymorphism over multiple arguments by type and arity. It’d be closer to say a class encapsulates member methods, but dynamic OOP languages may allow users to monkeypatch classes at will. CLOS is considered OOP and its classes don’t encapsulate methods at all; point is OOP is a more diverse paradigm than you’re portraying.

And we do that, but you probably mean formal interfaces that could involve reflection, not just documentation. The disconnect here is you expect “interface inheritance”, which implies designating interfaces per type. Julia isn’t OOP, so its interfaces are a set of callee methods. The few simpler Base interface methods effectively dispatch over one argument so those are equivalent to interfaces being implemented per type, but with multimethods in general, an interface can be implemented per tuple of types. A similar principle applies to Holy traits.

Another issue is that implementing a Julia interface isn’t as simple as defining a particular set of methods. Many methods are marked “optional”, but they’re more “do this if you want caller methods to work.” If I need methods that mutates arrays, setindex! isn’t really optional for my mutable array type. That particular case could be split into MutableArray and ImmutableArray traits, but could we generally split an interface into sub-interfaces that fit all the caller methods’ usages of interface methods? The only certainty there is how much more complicated the interface gets. However we end up formalizing interfaces, it’ll probably look very different from straightforward OOP.

Again, you’re asking for reasonable things, but they clash with the features and tradeoffs Julia already decided on, which are not things a major revision can undo. I could also argue that referential transparency is so useful for maintenance, debugging, and testing that Julia 2.0 should disallow reassignments and remove while/for loops, and someone would rightfully turn my attention back to the existing functional programming languages. Inspiration from another paradigm’s features for the established paradigm is a healthier expectation than zigzagging among many different paradigms whenever we find a few things to like.

3 Likes

You’re overthinking it. The point of portraying OOP is not to make it diverse, but to make it simple. If you can’t summarize then everything is ifs and buts, and there would be no movement trying to be made at all like you can see with JuliaHEP 2024 above.

Hardly. If one wants features from OOP languages, then one should pay attention to what how those OOP languages actually work, including their differences. Your argument would be stronger if your example of a successful OOP language making its big break in a major revision was either historically accurate or has all the features you say are important.

I watched the talk, it didn’t look to me that they held a workshop to do nothing, but you’re free to argue with them about that.

2 Likes

Julia isn’t successful in general-purpose enterprise settings because it lacks a mechanism like interfaces or traits to nail down unfamiliar logical structures. It’s extremely disorienting to navigate larger Julia codebases without being familiar with the domain because of this. This sort of slides by the Julia language because so much of it is technical and mathematical packages, which are ofc used by very technical and mathematically inclined users who are more familiar with it.

Compare this to a typical enterprise Java app or Go app where an average user can step into a large code base and suss out where their attention needs to be spent by using the language features. Go in particular makes this really nice.

I’ve said this before in a more inflammatory way, but the presence of interfaces/traits alone will all but ensure that Mojo eats Julia’s lunch in terms of general purpose usage. Maybe Julia will always stick around for the very mathy people, which is fine, but it could also just easily add features for 2.0 to mitigate this issue for thousands or maybe tens of thousands of potential Julia users. Who doesn’t want Python-looking code but really fast?

3 Likes

I think there is a subjective component to what you’re saying.
I love diving into big Julia code bases, and know little languages that make it so easy - but the tools are completely different, since it’s only fun if you have an interactive session, where you run part of the code and try things out and inspect the method tree from within Julia etc.
So a very different workflow from Java - which I really dread to dive into, same goes for C++, two languages I’m pretty familiar with and I’m still completely overwhelmed by the insane amount of boilerplate.
But still, I have to admit there’s a bias from my side here as well, since I know Julia ~10x better at this point, and also usually have much less patient to dive into a C++/Java code base.

I guess if you’re used to dive into a Java code base, mainly with the help of e.g. Eclipse, it’s quite a different deal, and if you apply the same workflow to Julia, you will be very disappointed.

8 Likes

Go also refuses method overloading. The entry seems dismissive of a popular form of polymorphism at first glance, but they’re just sparing readers the deep dive. This has been asked before by language enthusiasts and it’s readily apparent that mixing multimethods with Go’s object-oriented multiple interfaces easily runs into dispatch ambiguity, though they flubbed Go’s interfaces a bit there. It’s very easy to dismiss Go because of this, but the reasonable thing to do is weigh the tradeoffs, not hyperfocus on an advantage and exaggerate its importance in computing.

Oh really “easily”? - I guess it might need a lot of work and thinking.

On the other side, as has been repeated many times, interfaces etc. can probably be implemented in a non-breaking way, which means by definition staying v1.x - and that’s a good thing.

2 Likes

This topic was automatically closed after 2 days. New replies are no longer allowed.