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

Use Val(x) and f(::Val{x}) #22475

Merged
merged 2 commits into from
Jul 6, 2017
Merged

Use Val(x) and f(::Val{x}) #22475

merged 2 commits into from
Jul 6, 2017

Conversation

andyferris
Copy link
Member

@andyferris andyferris commented Jun 22, 2017

@JeffBezanson as discussed. Instead of calling f(Val{x}) and method definitions f(::Type{Val{x}}) where x = ..., we use f(Val(x)) and f(::Val{x}) where x = .... There is a new @pure function for Val(x) -> Val{x}(), a show override, and a docstring/doctest.

This is WIP and so far only "upgrades" two functions (ntuple and fill_to_length). I am currently intending to replace I have replaced all uses of Val{x} in Base with the new constructor (except for specific inference tests targeting type parameters).

Also, what does this mean when building? I'm kind-of lost with the documentation system.

WARNING: replacing docs for 'Base.Val :: Union{}' in module 'Base'.

@fredrikekre
Copy link
Member

fredrikekre commented Jun 22, 2017

Also, what does this mean when building? I'm kind-of lost with the documentation system.

WARNING: replacing docs for 'Base.Val :: Union{}' in module 'Base'.

You are replacing the current docstring here with your new one. You can probably merge them into the same docstring and delete the one in helpdb/Base.jl

@martinholters
Copy link
Member

Are there any tangible benefits, e.g. in terms of inferability or time needed for inference? (Just curious, not that I'm against this PR if there aren't.)

@andyferris
Copy link
Member Author

While I feel it's primarily aesthetic, you can also infer multiple return Val instances from a function. I.e. they can go into a tuple without being inferred as Tuple{Vararg{DataType, N}}.

@deprecate literal_pow{N}(a,b , ::Type{Val{N}}) literal_pow(f, Val(N))
#@deprecate IteratorsMD.split(t, V::Type{Val{n}}) IteratorsMD.split(t, Val(n))
@deprecate sqrtm{T,realmatrix}(A::UpperTriangular{T},::Type{Val{realmatrix}}) sqrtm(A, Val(realmatrix))
@deprecate lufact(A, pivot::Union{Type{Val{false}}, Type{Val{true}}}) lufact(A, pivot)
Copy link
Member

Choose a reason for hiding this comment

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

The replacement syntax is the same!? Wont this create an infinite loop?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes - yes it would :) Thanks @fredrikekre

@andyferris
Copy link
Member Author

See also earlier discussion in #9452

@andyferris andyferris changed the title WIP Use Val(x) and f(::Val{x}) Use Val(x) and f(::Val{x}) Jun 24, 2017
@andyferris
Copy link
Member Author

andyferris commented Jun 24, 2017

I wasn't expected to change 42 45 files, but I think I'm done now. Fingers crossed for CI.

@deprecate ntuple{N}(f, ::Type{Val{N}}) ntuple(f, Val(N))
@deprecate fill_to_length{N}(t, val, ::Type{Val{N}}) fill_to_length(t, val, Val(N))
@deprecate literal_pow{N}(a,b , ::Type{Val{N}}) literal_pow(f, Val(N))
#@deprecate IteratorsMD.split(t, V::Type{Val{n}}) IteratorsMD.split(t, Val(n))
Copy link
Member Author

Choose a reason for hiding this comment

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

the @deprecate macro was not happy with this. Probably unnecessary.

Copy link
Member

Choose a reason for hiding this comment

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

You can @eval the deprecation into the IteratorsMS module.

Copy link
Member

Choose a reason for hiding this comment

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

IIRC, happily @deprecate now accepts a module as well? :)

Copy link
Member

Choose a reason for hiding this comment

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

Nope

julia> @deprecate Base.foo Base.bar
ERROR: invalid usage of @deprecate

Could be fixed though.

Copy link
Contributor

Choose a reason for hiding this comment

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

@eval accepts a module, and you can put the @deprecate in an @eval block

Copy link
Member

Choose a reason for hiding this comment

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

Ah yes, it's @eval module @dep... that I was remembering :).

Copy link
Member

Choose a reason for hiding this comment

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

Thats what I suggested 😄

Copy link
Member

Choose a reason for hiding this comment

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

Indeed :)

@@ -134,7 +134,7 @@ Base.@propagate_inbounds _broadcast_getindex(::Any, A, I) = A[I]
## Broadcasting core
# nargs encodes the number of As arguments (which matches the number
# of keeps). The first two type parameters are to ensure specialization.
@generated function _broadcast!(f, B::AbstractArray, keeps::K, Idefaults::ID, A::AT, Bs::BT, ::Type{Val{N}}, iter) where {K,ID,AT,BT,N}
@generated function _broadcast!(f, B::AbstractArray, keeps::K, Idefaults::ID, A::AT, Bs::BT, ::Val{N}, iter) where {K,ID,AT,BT,N}
Copy link
Member Author

Choose a reason for hiding this comment

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

Is this public interface (meaning - does this require a @deprecate)?

Copy link
Member

Choose a reason for hiding this comment

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

Should be fine without :).

Copy link
Contributor

Choose a reason for hiding this comment

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

unless packages have been extending it...

Copy link
Contributor

Choose a reason for hiding this comment

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

DataArrays, StaticArrays, and IndexedTables define methods for something called _broadcast! but I don't think they're importing the Base one

@fredrikekre
Copy link
Member

There is an export true/false option for @deprecate, @deprecate old(args...) new(args...) false IIRC

@fredrikekre
Copy link
Member

fredrikekre commented Jun 24, 2017

fill_to_length, literal_pow and cat_t should not be exported, so you can append a false after the new definitions in deprecated.jl

@@ -1485,6 +1485,23 @@ end
using .DSP
export conv, conv2, deconv, filt, filt!, xcorr

# PR #22475
@deprecate ntuple{N}(f, ::Type{Val{N}}) ntuple(f, Val(N))
Copy link
Member

Choose a reason for hiding this comment

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

use new where syntax here and below?

@deprecate ntuple(f, ::Type{Val{N}}) where {N} ntuple(f, Val(N))

"""
Val(c)

Constructs a `Val{c}()`, which contains no run-time data. Types like this can be used to
Copy link
Member

Choose a reason for hiding this comment

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

"Construct" instead of "Constructs" to comply with the usual phrasing of docstrings?

end

Val(x) = (@_pure_meta; Val{x}())

show(io::IO, ::Val{x}) where {x} = print(io, "Val($x)")
Copy link
Member

Choose a reason for hiding this comment

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

Why this? Shouldn't we show the object for what it is, i.e. Val{T}() (as it does by default already)

Copy link
Member Author

Choose a reason for hiding this comment

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

The cool kids like "print it like you write it" these days.

I personally feel this much more aesthetic. There is a doc string for Val which explains the representation.

Copy link
Member

Choose a reason for hiding this comment

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

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

? 😄

Copy link
Member

Choose a reason for hiding this comment

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

It does kind of make sense to show it the way it's expected to be written, but we don't generally do this in other cases, e.g.

julia> Ref(0)
Base.RefValue{Int64}(0)

Copy link
Member

Choose a reason for hiding this comment

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

And also, Val(x) is just for convenience; Val{x}() is the "real" constructor, right? :)

Copy link
Member Author

@andyferris andyferris Jun 26, 2017

Choose a reason for hiding this comment

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

The RefValue example exposes larger differences, e.g. a concrete type, and we allow RefValue{Any}(0) also. In the case of Val the relation is (more-or-less) one-to-one; I wouldn't have done it otherwise and in my opinion the printing of RefValue is 100% correct.

Copy link
Member

Choose a reason for hiding this comment

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

I think I'm ok with either printing in this case.

@andyferris andyferris force-pushed the master branch 3 times, most recently from 30463e4 to 51998dc Compare June 29, 2017 14:13
@andyferris
Copy link
Member Author

andyferris commented Jun 29, 2017

There is a single spawn test failure on OSX throwing an InterruptException on travis. I'm guessing this is unrelated.

Other than that - is this good to go?

@deprecate literal_pow{N}(a,b , ::Type{Val{N}}) literal_pow(f, Val(N)) false
@eval IteratorsMD @deprecate split{n}(t, V::Type{Val{n}}) split(t, Val(n)) false
@deprecate sqrtm{T,realmatrix}(A::UpperTriangular{T},::Type{Val{realmatrix}}) sqrtm(A, Val(realmatrix))
@deprecate lufact(::AbstractMatrix, ::Type{Val{false}}) lufact(A, Val(false))
Copy link
Contributor

Choose a reason for hiding this comment

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

missing A on the input ?

# PR #22475
@deprecate ntuple{N}(f, ::Type{Val{N}}) ntuple(f, Val(N))
@deprecate fill_to_length{N}(t, val, ::Type{Val{N}}) fill_to_length(t, val, Val(N)) false
@deprecate literal_pow{N}(a,b , ::Type{Val{N}}) literal_pow(f, Val(N)) false
Copy link
Contributor

Choose a reason for hiding this comment

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

strange spacing on the inputs, f not defined?

@deprecate cat{N}(::Type{Val{N}}, A::AbstractArray...) cat(Val(N), A...)
@deprecate cat{N}(::Type{Val{N}}, A::SparseArrays._SparseConcatGroup...) cat(Val(N), A...)
@deprecate cat{N}(::Type{Val{N}}, A::SparseArrays._DenseConcatGroup...) cat(Val(N), A...)
@deprecate cat_t{N,T}(::Type{Val{N}}, ::Type{T}, A, B) cat(Val(N), T, A, B) false
Copy link
Contributor

Choose a reason for hiding this comment

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

should this call cat_t ?

Return `Val{c}()`, which contains no run-time data. Types like this can be used to
pass the information between functions through the value `c`, which must be an `isbits`
value. The intent of this construct is to be able to dispatch on constants directly (at
compile time) without having test the value of the constant at run time.
Copy link
Contributor

Choose a reason for hiding this comment

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

having to test

compile time) without having test the value of the constant at run time.

### Example

Copy link
Contributor

Choose a reason for hiding this comment

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

use

# Examples
```jldoctest

single #, plural Examples, no blank

@@ -208,7 +208,7 @@ chol(x::Number, args...) = ((C, info) = _chol!(x, nothing); @assertposdef C info
# cholfact!. Destructive methods for computing Cholesky factorization of real symmetric
# or Hermitian matrix
## No pivoting (default)
function cholfact!(A::RealHermSymComplexHerm, ::Type{Val{false}}=Val{false})
function cholfact!(A::RealHermSymComplexHerm, ::Val{false}=Val(false))
Copy link
Contributor

Choose a reason for hiding this comment

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

cholfact! and cholfact are missing from news and deprecations

function reshape(parent::AbstractArray, ndims::Type{Val{N}}) where N
reshape(parent, rdims(Val{N}, indices(parent)))
reshape(parent::AbstractArray{T,N}, ndims::Val{N}) where {T,N} = parent
function reshape(parent::AbstractArray, ndims::Val{N}) where N
Copy link
Contributor

Choose a reason for hiding this comment

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

mention in news

@fredrikekre
Copy link
Member

Should do something with these too I think

julia/base/deprecated.jl

Lines 1356 to 1362 in 71d7c16

# PR #22188
@deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) cholfact!(Hermitian(A, uplo), Val{false})
@deprecate cholfact!(A::StridedMatrix, uplo::Symbol) cholfact!(Hermitian(A, uplo))
@deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{false}}) cholfact(Hermitian(A, uplo), Val{false})
@deprecate cholfact(A::StridedMatrix, uplo::Symbol) cholfact(Hermitian(A, uplo))
@deprecate cholfact!(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact!(Hermitian(A, uplo), Val{true}, tol = tol)
@deprecate cholfact(A::StridedMatrix, uplo::Symbol, ::Type{Val{true}}; tol = 0.0) cholfact(Hermitian(A, uplo), Val{true}, tol = tol)
since they will be in the same release as this, or they will suggest something that is also deprecated. Should be enough to updtae the replacement for them. There are some other Val usage in the 0.6 section of deprecated.jl but should not matter.

@andyferris andyferris force-pushed the master branch 2 times, most recently from 2bdbb63 to 76c4a2b Compare July 3, 2017 06:32
@JeffBezanson
Copy link
Member

👍
There is some discussion of this in the manual that needs to be updated as well. Otherwise looks good to go.

@tkelman
Copy link
Contributor

tkelman commented Jul 3, 2017

The timeout on 64 bit Linux Travis is a bit unexpected.

@tkelman
Copy link
Contributor

tkelman commented Jul 3, 2017

@nanosoldier runbenchmarks(ALL, vs = ":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

Replaces `f(Val{x})` on call sites with `f(Val(x))`, using a new
`@pure` function `Val(x) = Val{x}()`. This simplifies the method
definitions from `f(::Type{Val{x}}) where x` to `f(::Val{x}) where x`.

This form also has the advantage that multiple singleton instances
can be put in a tuple and inference will work (similarly with
multiple-return functions).
@andyferris
Copy link
Member Author

Thanks everyone for reviewing!

I have rebased, and updated the manual to reflect this change.

@andyferris
Copy link
Member Author

Appveyor error is something about pkg and libgit2 on Windows...

@JeffBezanson
Copy link
Member

Merge?

@andyferris
Copy link
Member Author

Yes, please (I can't do it).

@JeffBezanson JeffBezanson merged commit 259996c into JuliaLang:master Jul 6, 2017
ararslan added a commit to JuliaLang/Compat.jl that referenced this pull request Jul 19, 2017
ararslan added a commit to JuliaLang/Compat.jl that referenced this pull request Jul 19, 2017
ararslan added a commit to JuliaLang/Compat.jl that referenced this pull request Jul 19, 2017
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

Successfully merging this pull request may close these issues.

7 participants