Supertype operator <:

Math operators can be used in three forms

#all equivalent

The supertype operator doesn’t seem to allow the 3rd form.

 myType <: mySuperType
<:(mySuperType)(myType)   #doesn't work

The 3rd form would allow:

filter( ==(mySuperType) ∘ supertype ∘ typeof, myVectorOfStructs )

To be written as:

filter( <:(mySuperType) ∘ typeof, myVectorOfStructs )

For what it’s worth, the filter could be made a little simpler by using isa:

julia> filter(x -> x isa Integer, Any[2, 3.14])
1-element Vector{Any}:

The partially applied versions of operators are added on a case-by-case basis, which is a bit ad-hoc. We wouldn’t need any of those partially applied methods if we had underscore currying.

1 Like

isa doesn’t allow the 3rd form either.

a isa b
isa(b)(a)           #doesnt work

If it did this would make the filter even simpler.

filter(  isa(muSuperType),  myVectOfStructs )

Would it be possible to allow an expression of the form “Operator RHS” to be used in a map or filter function such that the Vector elements fill in the LHS. e.g.

map(    + 1,     1:5    )

filter( < 3,     1:5    )

filter( isa Int,  [1,2,"a","b"] )

I think I had seen a discussion about something like this, but I can’t find it now. The recommendation there was that it’s better to use Base.Fix1/2 in such cases, as it’s much more general, and can turn any operator into a currying version.

julia> filter(Base.Fix2(isa, Int), Any[1,2,"3", 4.0])
2-element Vector{Any}:

It’s not as aesthetically pleasing, though. I think many people would like isa(::Type) to be available, but this might be tricky as isa is a built-in function currently, and methods can’t be added to it.


You’re probably thinking of this

as well as

The underlying reason why isa(foo) and <:(foo) can’t be just defined is that they are some of the few builtin functions julia has - you can’t just add methods to it, and adding a single argument version is non-trivial.

These are not the same - consider a type hierarchy like this:

  • mySuperType
    • abstract1
      • concrete1
    • abstract2
      • concrete2

and filtering a vector with element type Union{concrete1, concrete2}. The first version of your filter gives an empty array, while the second one gives the input array.

This isn’t really generally accurate. Operators (not just maths operators) can be used in two ways, infix/prefix and function call. Your third form above is just function call syntax where a single argument method has been added, which is done on a case-by-case basis. It is not generally the case that you can use the third form for operators. (For example, +(4) just equals 4, and +(4)(3) equals 12, not 7, since it is parsed as multiplication by juxtaposition.)