-
Notifications
You must be signed in to change notification settings - Fork 17
Conversation
src/NamedTuples.jl
Outdated
fields[i] = sym != nothing?sym:Symbol( "_$(i)_") | ||
typs[i] = typ | ||
fields[i] = sym != nothing ? sym : Symbol( "_$(i)_") | ||
typs[i] = typ != nothing ? typ : Any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ===
or !==
when comparing against `nothing.
src/NamedTuples.jl
Outdated
ty = create_namedtuple_type( fields ) | ||
else | ||
ty = Expr(:curly, :NamedTuple, (fields...)) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this just call make_tuple
?
The deprecations on 0.7 should also be addressed: https://travis-ci.org/JuliaData/NamedTuples.jl/jobs/369297897 |
src/NamedTuples.jl
Outdated
export @NT | ||
|
||
if VERSION < v"0.7.0-DEV.2738" | ||
export NamedTuple |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is fine to export NamedTuple
on Julia 0.7
src/NamedTuples.jl
Outdated
end | ||
end | ||
|
||
function create_struct_expr(name::Symbol, fields::Vector{Symbol}, mod::Module = NamedTuples) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mod
isn't used
src/NamedTuples.jl
Outdated
return Expr( :curly, ty, typs... ) | ||
else | ||
return Expr(:curly, ty, Expr(:curly, :Tuple, typs...)) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whitespace issues. Could we switch to using Tuple
on 0.6?
src/NamedTuples.jl
Outdated
return q | ||
end | ||
# Deep hash | ||
@generated function Base.hash(nt::NamedTuple, hs::UInt64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks to be the 32-bit issue. Should be hs::UInt
and not hs::UInt64
src/NamedTuples.jl
Outdated
""" | ||
function NamedTuple{names}(args...) where {names} | ||
NamedTuple{names}(args) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want:
function NamedTuple{names}(args...) where {names}
NamedTuple{names, typeof(args)}(args)
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are just helper functions to allow NamedTuple(args)
rather than NamedTuple((args))
fixing the types happens below. I wanted to let Base.NamedTuple
deal with as much as possible as far as declarations go.
src/NamedTuples.jl
Outdated
|
||
function NamedTuple{names,T}(args...) where {names, T <: Tuple} | ||
NamedTuple{names, T}(args) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function NamedTuple{names,T}(args...) where {names, T <: Tuple}
NamedTuple{names, T}(args::T)
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would break the conversion of @NT(a::Int64)(2.0)
to NamedTuple{(:a,), Tuple{Int64}}(2.0)
src/NamedTuples.jl
Outdated
# TODO: to make modules containing named tuples precompile-able, change `= NamedTuples` to `= current_module()` | ||
function create_namedtuple_type(fields::Vector{Symbol}, mod::Module = NamedTuples) | ||
escaped_fieldnames = [":$i" for i in fields] | ||
name =Symbol(string("NamedTuple{(", join(escaped_fieldnames,", "), ",)}")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the original was less confusing when the type was printed. That said we should probably do:
function Base.show(io::IO, ::Type{<:NamedTuple{K, T}}) where {K, T<:Tuple}
print(io, "NamedTuple{$K, $T}")
end
to display the type nicely on 0.6.
Changes `NamedTuple` to `NamedTuple{K, V<:Tuple}` and moves expr construction to separate function
- Removes deprecated doc formatting - Disables functions implemented in Base - Uses Base `NamedTuple` instead of local struct - Disables tests for broadcast (intentionally disabled in Base) - Allows `NamedTuple{K,T}()` construction format
Fixes 0.7 deprecations Adds macro to replace auto-naming functionality
src/NamedTuples.jl
Outdated
end | ||
print(io, ")") | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The printing for a NamedTuple
with a single field should have a trailing comma: (a = 1,)
instead of (a = 1)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Julia 0.7:
julia> (a=1)
1
julia> (a=1,)
(a = 1,)
src/NamedTuples.jl
Outdated
macro NT( expr... ) | ||
args = collect( expr ) | ||
if isa(args, Vector{Symbol}) | ||
Base.depwarn("\"@NT( a, b )\" syntax for NamedTuple Type declaration is deprecated, use \"NamedTuple{(:a, :b)}\" instead.", Symbol("@NT")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be dynamic based upon the inputs:
Base.depwarn("\"@NT($(join(expr, ", ")))\" syntax for NamedTuple Type declaration is deprecated, use \"NamedTuple{$(repr(expr))}\" instead.", Symbol("@NT"))
would result in:
julia> @NT(c, d)
WARNING: "@NT(c, d)" syntax for NamedTuple Type declaration is deprecated, use "NamedTuple{(:c, :d)}" instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Type" should be lowercase
Just a warning/heads up: I will upper bound all the packages from the Queryverse to not use this version on julia 0.6. That is a lot of packages, and some of them quite low-level, so in essence that would probably mean that a lot of folks would never get this update on 0.6. My migration plan for Queryverse right now is to just do a breaking release once 0.7 is out that only works on 0.7, i.e. drop 0.6 support at that time. I do not plan to have a version that supports both 0.6 and 0.7 at the same time. |
src/NamedTuples.jl
Outdated
|
||
# Either call the constructor with the supplied values or return the type | ||
if( !construct ) | ||
if len == 0 | ||
Base.depwarn("\"@NT( a, b )\" syntax for NamedTuple Type declaration is deprecated, use \"NamedTuple{(:a, :b)}\" instead.", Symbol("@NT")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, we probably shouldn't make an empty named tuple. Probably this should be an error which raises an error before we construct the type.
Completely reasonable plan. We still should try to support an easy transition for package that do want to support 0.6 and 0.7. |
I guess the question is whether that can be done without deprecations? The moment we introduce deprecations here, I'll have to add the upper bounds in my packages, and that will then hold things back for a lot of folks... |
I'm not sure what the issue with deprecations is. The deprecations which are being proposed here are to use a syntax which is much closer to what is being used in Julia 0.7 named tuples. If this gets merged there will be deprecations introduced for those using the NamedTuples package and the Overall this should help make your package work much closer to how it will work when you drop Julia 0.6 support. |
return ty | ||
end | ||
return Expr( :curly, ty, typs... ) | ||
syms = [repr(i) for i in fields] | ||
Base.depwarn("\"@NT($(join(exprs, ", ")))\" syntax for NamedTuple type declaration is deprecated, use \"NamedTuple{($(join(syms, ", "))), Tuple{$(join(typs, ", "))}}\" instead.", Symbol("@NT")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
($(join(syms, ", "))
needs a trailing comma when there is only one element. This works join(syms, ", ") * (length(syms) == 1 ? "," : "")
but is rather ugly
@@ -1 +1,2 @@ | |||
julia 0.6 | |||
Compat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to set a minimum version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is Compat
needed here or only for tests?
NamedTuple{(:a, :b)} -> Defines a tuple with a and b as members | ||
NamedTuple{(:a, :b), Tuple{Int64, Float64}} -> Defines a tuple with the specific arg types as members | ||
|
||
@NT( a = 1, b = "hello"). -> Defines and constructs a tuple with the specifed members and values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random .
One potential gotcha with this PR we may want to address in the README is that on Julia 0.7: julia> t = (a=1,)
(a = 1,)
julia> typeof(t) == NamedTuple{(:a,), Tuple{Int64}}
true However with NamedTuples on Julia 0.6: julia> t = NamedTuple{(:a,), Tuple{Int64}}(1)
(a = 1,)
julia> typeof(t) == NamedTuple{(:a,), Tuple{Int64}}
false
julia> typeof(t) <: NamedTuple{(:a,), Tuple{Int64}}
true
julia> typeof(t)
NamedTuple{(:a,), Tuple{Int64}} The new |
$(gen_namedtuple_ctor_body(n, args)) | ||
# Pretty print type information | ||
function Base.show(io::IO, ::Type{<:NamedTuple{K, T}}) where {K, T<:Tuple} | ||
print(io, "NamedTuple{$K, $T}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I change my mind with this. We should remove it to avoid confusion. See: #52 (comment)
|
||
return q | ||
if VERSION < v"0.7.0-DEV.2738" | ||
abstract type NamedTuple{K, V<:Tuple} end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets change this to:
abstract type NamedTuple{names, T<:Tuple} end
to match the type parameter variables used in Julia 0.7: https://github.com/JuliaLang/julia/blob/9f5351c36abb1cc7c7e1df9b1b73df696401d13a/base/namedtuple.jl#L58
nt = NamedTuple{(:a, :b), Tuple{Empty, Int}} | ||
@test nt.parameters[2] == Tuple{Empty, Int} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test is using the abstract type rather than the constructed struct. See: #52 (comment)
I just creates extra work: instead of just having one update cycle once julia 0.7 comes out, I would have to update packages twice, now to fix the deprecations, and then again when julia 0.7 comes around. At least for me the solution would be to just not fix the deprecations on 0.6 and instead add upper bounds in REQUIRE. From my point of view that works, but because some of the packages I would upper bound are so deep in the stack, it would mean that a lot of systems would never see this new release here, which might kind of defeat the purpose (not sure). |
|
||
@test typeof( @NT( a::Int64, b::Float64 )(1, 3.0) ) == typeof( @NT( a = 1, b = 2.0 )) | ||
@test typeof( NamedTuple{(:a,:b), Tuple{Int,Float64}}(1, 3.0) ) == typeof( @NT( a = 1, b = 2.0 )) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be useful tests to add:
@test typeof(@NT(a = 1, b = 2.0)) <: NamedTuple{(:a, :b), Tuple{Int,Float64}}
if VERSION < v"0.7.0-DEV.2738"
@test typeof(@NT(a = 1, b = 2.0)) != NamedTuple{(:a, :b), Tuple{Int,Float64}}
else
@test typeof(@NT(a = 1, b = 2.0)) == NamedTuple{(:a, :b), Tuple{Int,Float64}}
end
@test @NT( a ) == @NT( a ) | ||
@test @NT( a ) != @NT( b ) | ||
@test NamedTuple{(:a,)} == NamedTuple{(:a,)} | ||
@test NamedTuple{(:a,)} != NamedTuple{(:b,)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test should be comparing the constructed struct types not the abstract type
@davidanthoff it seems odd to me that you're willing to put in the work to change the REQUIRE file to add an upper bound to a requirement but not revise the code to clean up deprecations. I'll definitely say wait and see until this PR has stabilized before making any choices as to upper bounding or updating. If you do think it's too much work to support the next release I can (or one of my team members) do the update on your behalf. |
After looking over this code it may be best if we divide some of the functionality like this:
If we want to go 100% deprecation free we could leave |
Well, I think the etiquette in METADATA is that if you want to tag a new version that breaks/negatively affects other packages, you have to put the upper bounds into METADATA, so that should be no work for me :) This is really just about my time budget: I just don't have the time right now to do two sweeps of deprecation updates, once for this and then again for 0.7. Introducing breaking changes that low in the stack is just hugely expensive for me. My guess is that there are about 20 packages that might need updating/testing, everything needs to be synchronized, tested in sync etc. Some of those packages I control, others I don't. A lot of that probably can't be outsourced to someone else, all the tagging/testing/coordinating would probably end up on my plate at the end of the day. I guess my preference in general is that packages that have many dependencies and are low in the stack are super, super conservative in terms of deprecations/breaking changes. If they do make breaking changes, it just causes this enormous ripple effect of extra work for other folks. Sometimes that can't be avoided, but it would be great if it could be rare and we would try to avoid when at all possible. I guess another option might be to just fork NamedTuples.jl: create a NamedTuples2.jl that works on julia 0.6 and 0.7, and folks that want to support both platforms could use that. The benefit of that would be that other packages could just stay on NamedTuples.jl for julia 0.6 and wouldn't require any extra work right now. |
In an effort to keep the changes to support Julia 0.7 to a minimum the critical parts of this PR have been made into #55. |
This PR deprecates any functions not supported by
Base.NamedTuple
in v0.7. It deprecates using@NT
to declare a type so that:@NT(a, b)
-> Deprecated in favor ofNamedTuple{(:a, :b)}
@NT(a::Int64, b::Float64)
-> Deprecated in favor ofNamedTuple{(:a, :b), Tuple{Int64, Float64}}
@NT(a, b)(1, "hello")
-> Deprecated in favor ofNamedTuple{(:a, :b)}(1, "hello")
@NT(a::Int64)(2.0)
-> Deprecated in favor ofNamedTuple{(:a,), Tuple{Int64}}(2.0)
@NT(a = 1, b = "hello")
-> remains the same@NT(::Int64, ::Float64)
-> Deprecated in favor of new macro@nt(::Int64, ::Float64)
It also adds Appveyor.
Closes #51