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

Feature Proposal: Anonymous Subtype Parameters #16086

Closed
oxinabox opened this issue Apr 28, 2016 · 5 comments
Closed

Feature Proposal: Anonymous Subtype Parameters #16086

oxinabox opened this issue Apr 28, 2016 · 5 comments

Comments

@oxinabox
Copy link
Contributor

I've been thinking about this for a while; and I thought I should share the notion.
I'm happy to have it shouted down as a bad idea (particularly if a good explanation is given),
but I figured I should share, incase it is infact a good idea.

We all know that having a container type (etc) contain abstract types is slow.,
thus normal habit for this case, is to instead have containers which contain a consistent, but generic subtype of that abstract type -- because any given container is normally consistent.

All examples here are from real code

EG1

instead of writing

function predict(c::LinearClassifier, x::Array{AbstractFloat})

We write:

function predict{F<:AbstractFloat}(c::LinearClassifier, x::Array{F})

But that is a little harder to read -- the type of x is now spread into two locations.
Not too bad though.

Eg 2 Now a more complex function.

Consider:

function train_one!(c::LinearClassifier, x::Array{AbstractFloat}, y::Int64, input_gradient::Array{AbstractFloat}, α::AbstractFloat=0.025f0)

If the type of x and the type of input_gradient are destined to be the same then:

function train_one!{F<:AbstractFloat}(c::LinearClassifier, x::Array{F}, y::Int64, input_gradient::Array{F}, α::AbstractFloat=0.025f0)

But it turns out that, in this case, the type of x and the type of input_gradient are not necessarily the same. input_gradient comes from the greater training procedure -- which is currently Float32 to save on memory. x however could be a Float32 or a Float64 depending on what the input data (from an external source) is (The function always returns Float32).

So what we have is now:

function train_one!{F1<:AbstractFloat, F2<:AbstractFloat}(c::LinearClassifier, x::Array{F1}, y::Int64, input_gradient::Array{F2}, α::AbstractFloat=0.025f0)

That is looking pretty bad, now that I have multiple type parameters.
The type of x, and of input_gradient, now each involve cross-referencing two lists.
It could perhaps be better with better naming:

function train_one!{Fx<:AbstractFloat, Fgrad<:AbstractFloat}(c::LinearClassifier, x::Array{Fx}, y::Int64, input_gradient::Array{Fgrad}, α::AbstractFloat=0.025f0)

So what can we do about it?

The syntax/syntactic sugar I am proposing is that subtypes parameters be allowed without names in the argument types.
Exact syntax, I am not to sure on.
It could be GenericType{<:AbstractType}, or perhaps GenericType{_<:AbstractFloat},
or maybe something else. I'll use the first form for sake of examples.

So

Eg1'.
Before:

function predict{F<:AbstractFloat}(c::LinearClassifier, x::Array{F})

After:

function predict(c::LinearClassifier, x::Array{<:AbstractFloat})

Eg2
Before:

function train_one!{Fx<:AbstractFloat, Fgrad<:AbstractFloat}(c::LinearClassifier, x::Array{Fx}, y::Int64, input_gradient::Array{Fgrad}, α::AbstractFloat=0.025f0)

After:

function train_one!(c::LinearClassifier, x::Array{<:AbstractFloat}, y::Int64, input_gradient::Array{<:AbstractFloat}, α::AbstractFloat=0.025f0)

This can't replace named type parameters. As it does not allow you to say that multiple of your parameters have the same generic type.
But it does I think clean up the cases where each type parameter is used only once.

I'm not sure if it breaches the "every feature starts at -100 points" test.
But I wanted to present this as an option.

PS: Is their Julep writing guidelines somewhere? I'm happy to reformat this and add additional details.

@IainNZ
Copy link
Member

IainNZ commented Apr 28, 2016

I swear this has been proposed before, but I'm not sure how it was described at the time...

@IainNZ
Copy link
Member

IainNZ commented Apr 28, 2016

I think this: #6984

@oxinabox
Copy link
Contributor Author

@IainNZ I just found that. I think it is identical. I'll close this as a duplicate then.

@vtjnash
Copy link
Member

vtjnash commented Apr 28, 2016

you could also note that:
function train_one!(c::LinearClassifier, x::AbstractArray, y::Int64, input_gradient::AbstractArray, α::AbstractFloat=0.025f0)
is shorter still, but basically equivalent

@oxinabox
Copy link
Contributor Author

oxinabox commented Apr 28, 2016

@vtjnash Almost equiv, but not.
For two important reasons.

  1. It is very likely in this kind of code to be specializing SparseArrays differently to DenseArrays.
  2. In my particular case, it is not unlikely that I might mistakenly send an array of T<:AbstractString, instead of T<:AbstractFloat; and I want to get a method not found error, to let me know right away.

With that said is still might be worth it, until (when and if) point 1 occurs, to do so; to simplify code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants