Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syntactic sugar Foo{<:Bar} for Foo{T} where T<:Bar #20414

Merged
merged 6 commits into from
Feb 3, 2017

Conversation

stevengj
Copy link
Member

@stevengj stevengj commented Feb 2, 2017

This closes #6984 by adding the syntactic sugar Foo{<:Bar} for Foo{T} where T<:Bar. Update: similarly for Foo{>:Bar}.

It combines fine with the where syntax, e.g. TwoParams{S,<:Number} where S<:Real works.

If you nest types, then the where goes with the innermost type where the <: appeared, e.g. Vector{Foo{<:Bar}} is Vector{Foo{T} where T<:Bar}. You can nest these, e.g. Vector{<:Foo{<:Bar}} works.

@stevengj stevengj added the domain:types and dispatch Types, subtyping and method dispatch label Feb 2, 2017
@@ -711,6 +714,17 @@ julia> Pointy{Real} <: Pointy{Float64}
false
```

The notation `Pointy{<:Real}` can be used to express the Julia analogue of a
*covariant* type, while `Pointy{>:Int}` the analogue of a *contravariant* type,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a link above.

@JeffBezanson
Copy link
Sponsor Member

I have to admit, this is really nice.

As it happens, it's also gentler on the type/dispatch system, since it moves where clauses inside types relative to the current idiomatic way to write this, f{T<:Real}(x::Array{T}). You generally want T to cover as little of the signature as possible.

@stevengj
Copy link
Member Author

stevengj commented Feb 2, 2017

Since this syntax parses in Julia 0.5, it should be possible to make @compat function f(x::Array{<:Real}) method definitions transform to function f{T<:Real}(x::Array{T}), at least for the common non-nested case.

The nested case, e.g. f(x::AbstractArray{<:AbstractArray{<:Real}}), seems impossible to express in 0.5 since it requires triangular dispatch?

@JeffBezanson
Copy link
Sponsor Member

Yes, the nested case can't be expressed in 0.5. The closest thing might be to have Compat convert <:Real to TypeVar(:T, Real, false), just dropping a free typevar in there. But this doesn't seem likely to work in all cases.

@stevengj
Copy link
Member Author

stevengj commented Feb 2, 2017

Oh, cool, I didn't know about TypeVar in 0.5. That will make the @compat macro much easier to write. In Julia 0.5:

julia> @eval f(::Array{$(TypeVar(:T, Real, false))}) = 1
f (generic function with 1 method)

julia> f([2,3,4])
1

@stevengj
Copy link
Member Author

stevengj commented Feb 3, 2017

Should be good to merge?

@KristofferC
Copy link
Sponsor Member

Can you do ex Point{T<:Real} and use T in the body?

@stevengj
Copy link
Member Author

stevengj commented Feb 3, 2017

@KristofferC, no, if you want to do that I think you need to declare a type parameter explicitly. Otherwise, what is the scope for T? If you can figure out a good way to define it and we decide we want that, I think that would be a separate PR anyway.

Note that if you do f(x::Complex{T} where T<:Real) = T, this will throw an error on f(3+4im) because T is only defined inside the where statement, not in the body of the function.

@KristofferC
Copy link
Sponsor Member

Ah, thanks for explaining.

@JeffBezanson JeffBezanson merged commit c47412b into JuliaLang:master Feb 3, 2017
@JeffBezanson
Copy link
Sponsor Member

At some point we should take a pass through Base and use this where possible; that will help eliminate uses of to-be-deprecated static parameter syntax.

@stevengj stevengj deleted the covariant branch February 3, 2017 17:23
@stevengj
Copy link
Member Author

stevengj commented Feb 3, 2017

Unfortunately, it looks like the TypeVar trick won't work in the @compat macro because the second argument to TypeVar needs to be a type, but at the time of macro evaluation we only have a symbolic expression for the type.

@stevengj
Copy link
Member Author

stevengj commented Feb 3, 2017

(Of course, I could just eval the type expression in the current module and hope for the best. This will cover the common case of function definitions, I guess)

@yuyichao
Copy link
Contributor

yuyichao commented Feb 3, 2017

For most (all?) cases, simply leave a TypeVar(....) as expression in the code should work too.

@stevengj
Copy link
Member Author

stevengj commented Feb 3, 2017

@yuyichao, great, I thought the TypeVar had to be spliced in. I've submitted a Compat PR, it seemed remarkably easy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: Add syntactic sugar for covariant actual type parameters
5 participants