# Supertype operator <:

Math operators can be used in three forms

``````#all equivalent
1<2
<(1,2)
<(2)(1)
``````

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

`````` myType <: mySuperType
<:(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}:
2
``````

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(a,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}:
1
2
``````

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.

2 Likes

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.)

4 Likes