Providing traits, apis, generics, qualities, prototypes,

What are their strengths, capabilities, roles, and limitations separately?
What different/distinct strengths, capabilities, roles and limitations arise with cooperative subsets?

@jsarnoff There is very little that is actionable here and the question is very broad.
Do you have some specific ideas?

There are some traits implementations like @mauro3 's SimpleTraits.jl

For now that can be very useful. Stefan’s Julia 1.0 talk said it’ll maybe be there for 2.0. Maybe it’ll come sooner, maybe later. But it does seem to already be on people’s minds as something Julia should have.

@vchuravy I do have some ideas, all from my perspective that these different items share fundamental characteristic and are partially definable/realizable in a proto-compositive way that recognizes some substructural commons.

I opened the topic to allow focus to be shared over/through these ways which variously enhance, extend, ease Julia’s use and strengthen the artful part of designing solutions. This topic works when it serves to advance salience and soundness with any facilities that become selected for Julia’s v1.0.

That Traits (often coded using Tim Holy’s detailed coordination) are so performant has been important to their becoming well used as a distinct organizing principle for small groups of properties and allied sorts with overlapping properties.

For Julia’s own trait facility, the current labeled discrimination with traited multidispatch is the barest minimal capability. Grouping and group refinement through set theoretic unions and intersections of grouped traits (other unions or intersected unions, symmetric differences, anti-joins etc.) should work.

The trait facility becomes a better whole and more ready to support provision of e.g. apis and other composable specifiers or refining reifiers with making traits & trait groups be layerable to induce total ordering from which to resolve potential ambiguity in method dominance without needing user intervention. Layered order is immediately available to resolve potential ambiguity with method dominance when composing reusable aspects of some family of protocols to provide e.g. the protocol for interacting with a text stream.

The ability to induce distinct orderings from the same collection of traits and trait groups by relayering introduces useful dynamic responsiveness and making some protocols express context sensitivity.

1 Like

During the Saturday “Hackathon” day at JuliaCon 2016, Jeff had seemed to agree to a proposal for a simple trait syntax, that he felt could be done in the v0.6 time frame, and that fit in with his type system changes. I think Andy Ferris, Stefan, and Keno where also part of the discussion.
I’ve been hoping to hear whether that would come about in time for a v0.6 (or v0.7).

Since traits can have a major effect on just how people design APIs, I do hope that proposal does become part of the base language sooner rather than later! :wink:

Right, we got part-way through implementing some ideas at https://github.com/andyferris/Traitor.jl

The system worked in a limited set of circumstances. I paused development because it was impossible to have both “traitor” methods and standard methods on the same function (*), making it of limited usefulness. However, I can see the traits will be exceedingly useful, and IMHO the syntax worked really well.

Implementation relied on a generated function implementing a certain type of multiple dispatch. In what I can only describe as feeling particularly “Julian”, it was like instead of having multiple-inheritence on types, it was that the method signatures used multiple type or “trait” trees, one for each nominated trait, where Type{} is reduced to just one of such trait trees. I say “particularly Julian” in that multiple dispatch and generic methods take center stage unlike other object-oriented systems that support multiple inheritance. I think such a multi-faceted, multiple-dispatch algorithm could reasonably be built into Julia, with the caveat of even slower dynamic dispatch…

(*) - the main blocker at the time (**) was that there is no way to recover pre-existing methods. For this. it would have been useful to either have access to the raw (pre-lowered) code of a method or a way of using lowered code, so I can both override a method and insert its code into a different method.

(**) - I’m not even sure if the code runs anymore, since it was doing “interesting” things from @generated functions…

Is the syntax we’d been talking about (that I thought Jeff had kind of agreed to) been written up anywhere?
I remember the extra ::, and I think it also depended on using { } (which would be freed up by Jeff’s type changes), but that was 5 months ago, and my memory… :wink:

Why would you propose the Traitor.jl way instead of SimpleTraits.jl? The latter is more intuitive (to me) and doesn’t have the “no standard methods” problem, and we’ve tested that it compiles down to the fastest code possible. What is the advantage of Traitor traits?

This is a good place to clarify trait (intent, applicability, syntax, operational semantics, … i.e. the generalities and the details). Not speaking for others: afaik neither @tim.holy, @mauro3 nor @andyferris hold out their work as the completed spec for traits … each has contributed to our current, shared understanding of the mechanics, use and potential gain in expressiveness that traits will have brought to Julia. We are much, much closer to it than before – close enough to get this got.

Concerning syntax: SimpleTraits.jl now also supports the Traitor.jl syntax, like @traitfn f(x::::Tr1) = .... Note that whilst SimpleTraits.jl is pretty simple, i.e. not many bells and whistles, it should work well.

Concerning prototypes: after Jeff’s type-system revision it should be much easier. I’ll try to find the time to upgrade Traits.jl (but I’m not sure I’ll find it).

@mauro3 SimpleTraits.jl does work well. There are some things that are more difficult to bring inside of your implementation because of legit time constraints and because the implementation is within the context of v0.5. It would be better, I think, to sort the bells here so that the team can know what the community means by trait than to push that forward.

@ChrisRackauckas, I’ll try and explain the problems we attempted to solve in Traitor.jl. First a simple definition: I’ll use the word “method” to describe a standard method Julian method and the word “submethod” to describe one or more further specialized methods defined via Traitor.jl that is dispatched on by traits. Ideally, we would like:

  • Arbitrary many traits specified per trait-based “submethod”
  • Arbitrary many trait-based submethods per standard method
  • Cooexistance of a standard method which acts as a fallback if no more specific trait submethod is found
  • Computable traits (I see this is possible in SimpleTraits.jl)

Two other things which appealed to me in the design was Tim Holy’s idea to use a type tree to define traits - this lets you define as many trait instances per trait class as you like. That is, rather than just “has trait” or “doesnt’ have trait”. we can have “has EyeColour Blue”, “has EyeColour Brown” and “has EyeColour Green”… The other was the way that we dispatch using more :: as per normal, rather than requiring parameters (however with the upcoming where syntax this could also be revisited for syntax possibilities).

The one thing that looks really cool about SimpleTraits.jl is easy way traits can be derived from multiple inputs, and I don’t think Traitor.jl has done a good job of solving that.

But to conclude, the one thing I feel we all really need/want is the multiple-trait dispatch, where you have to go beyond the “Tim Holy trait trick” for dispatch (which can be done manually with relative ease, after all). It’s this that takes things to the next level.

2 Likes