Hi @visr. Thanks for your question
Here some advantages of Traits.@traits
over SimpleTraits.jl
-
(this is the most important advantage from my point of view)
no need for@traitimpl
or in general a separation between a standard julia function and a Trait -
the
@traits
functions are kind of compatible with existing standard julia functions in that they only overwrite the respective standard dispatch part. I.e.@traits f(a::Vector{Int}) = true # or more complex @traits f(a::Vector{Int}) where {isSometrait(a), isAnothertrait(a)} = true
really only overwrite the previous definition of
f(::Vector{Int})
, as usual in Julia. -
Bool
functions are just one concrete case of what@traits
supports (it seamlessly also works with multi-value traits like defined in the standard Julia Iterator interfaceBase.IteratorSize
) -
it works with multiple traits at once, in a transparent manner. Concretely if you dispatch on say both
isTrait1
andisTrait2
like@traits f(a) where {isTrait1(a)} = "first" @traits f(a) where {isTrait2(a)} = "second"
and have an
a
for which both isTrait1 and isTrait2 are true, you will be prompted to fill the ambiguity as usual, which can be solved by defining@traits f(a) where {isTrait1(a), isTrait2(a)} = "both"
-
also traits with two or more arguments are naturally supported. E.g. if
areinorder(a1, a2, a3, ...)
checks whethera1 <= a2 <= a3 ...
, this just works@traits f(a, b, c) where {areinorder(a, b, c)} = true
-
the implementation of
@traits
is very easy to explain on high-level. It just splits up the@traits
function into an outer and an inner function, the outer doing the standard julia dispatch, and the inner doing all the extra dispatch functionalities. -
a small syntax-nice-to-have: You can freely mix normal where syntax with the new syntax. No need for extra character
;
to separate them, but the implementation is smart enough to distinguish the different functionalities on its own. -
another syntax-nice-to-have: You do not need to have explicit TypeVariables like
@traits f(a::T) where {T, eltype(T)::String} = "something"
but if your function is similar to
eltype
in that if it gets avalue
, it returnseltype(typeof(value))
you can simply do@traits f(a) where {eltype(a)::String} = "something
There probably a couple of disadvantages, however I haven’t really used SimpleTraits.jl and hence cannot tell too much. One obvious point is that so far no Traitor.jl like syntax is supported.
Concerning your second question, how this approach compares to Traitor.jl, I hope that some points from above already clarify differences.
- One crucial aspect is again, that Traitor.jl relies on a special convention about Traits types.
Concretely, in Traitor.jl you have to define a proper type-hierarchy for your traits-types where the abstract type constructor is overloaded respectively - if I understood it correctly. WithTraits.@traits
nothing like that is needed, it just works with whatever function you have, e.g.Base.IteratorSize
. - Another thing is the syntax: I prefer using Julia
where
, while Traitor.jl syntax was developed before there even was a Juliawhere
, which back then was the best syntax available, but today feels a bit overloaded and unintuitive for me. - last but not least, the
Traits.@traits
syntax is already now pleasantly stable and I guess with only waiting until JuliaCon it is soon going to be production-level stable
I hope that can clarify some of your questions. And open some others