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

RFC: NamedTuple macro for easier type construction #34548

Merged
merged 7 commits into from
Feb 21, 2020

Conversation

stevengj
Copy link
Member

@stevengj stevengj commented Jan 28, 2020

Following #34498, #34505, and a recent discourse discussion, this PR defines (and exports) a macro @NamedTuple that provides a more convenient struct-like syntax for defining NamedTuple types:

julia> @NamedTuple{a::Int, b::String}
NamedTuple{(:a, :b),Tuple{Int64,String}}

julia> @NamedTuple begin
           a::Int
           b::String
       end
NamedTuple{(:a, :b),Tuple{Int64,String}}

If a ::Type is not specified, it is treated as ::Any (similar to a struct). This will only be useful if #34547 is resolved, however. (Alternatively, the PR could be changed to require a type specifier for all keys.) Abstractly typed fields of NamedTuple work fine.

@stevengj stevengj added the speculative Whether the change will be implemented is speculative label Jan 28, 2020
@StefanKarpinski
Copy link
Member

Might be even better to just have real syntax for this...

@stevengj
Copy link
Member Author

stevengj commented Jan 30, 2020

Might be even better to just have real syntax for this...

I don't think we would want NamedTuple{a::Int, b::String} (without the @) to work, since these aren't "really" the type parameters. Or did you have something else in mind?

(I suppose that anonymous struct ... end could produce a NamedTuple type, but that is confusing too.)

@StefanKarpinski
Copy link
Member

🤷‍♂ maybe the macro syntax is for the best.

base/namedtuple.jl Outdated Show resolved Hide resolved
@tkf
Copy link
Member

tkf commented Jan 31, 2020

Is it too evil to use @NamedTuple in show? Maybe at least for text/plain?

Co-Authored-By: Takafumi Arakaki <[email protected]>
@stevengj
Copy link
Member Author

Is it too evil to use @NamedTuple in show?

I vote for too evil, at least for now. We can reconsider later.

@tkf
Copy link
Member

tkf commented Jan 31, 2020

Re #34548 (comment) I'm seeing the effect of esc:

julia> module Demo1
       macro NamedTuple(ex)
           Meta.isexpr(ex, :braces) || Meta.isexpr(ex, :block) ||
               throw(ArgumentError("@NamedTuple expects {...} or begin...end"))
           decls = filter(e -> !(e isa LineNumberNode), ex.args)
           all(e -> e isa Symbol || Meta.isexpr(e, :(::)), decls) ||
               throw(ArgumentError("@NamedTuple must contain a sequence of name or name::type expressions"))
           vars = [QuoteNode(e isa Symbol ? e : e.args[1]) for e in decls]
           types = [esc(e isa Symbol ? :Any : e.args[2]) for e in decls]
           return :(NamedTuple{($(vars...),), Tuple{$(types...)}})
       end
       end  # module Demo1
Main.Demo1

julia> module Demo2
       macro NamedTuple(ex)
           Meta.isexpr(ex, :braces) || Meta.isexpr(ex, :block) ||
               throw(ArgumentError("@NamedTuple expects {...} or begin...end"))
           decls = filter(e -> !(e isa LineNumberNode), ex.args)
           all(e -> e isa Symbol || Meta.isexpr(e, :(::)), decls) ||
               throw(ArgumentError("@NamedTuple must contain a sequence of name or name::type expressions"))
           vars = [QuoteNode(e isa Symbol ? e : e.args[1]) for e in decls]
           types = [e isa Symbol ? :Any : e.args[2] for e in decls]
           return :(NamedTuple{($(vars...),), Tuple{$(types...)}})
       end
       end  # module Demo2
Main.Demo2

julia> struct Foo end

julia> Demo1.@NamedTuple{a::Foo}
NamedTuple{(:a,),Tuple{Foo}}

julia> Demo2.@NamedTuple{a::Foo}
ERROR: UndefVarError: Foo not defined
...

julia> @macroexpand Demo1.@NamedTuple {a::Foo}
:(Main.Demo1.NamedTuple{(:a,), Main.Demo1.Tuple{Foo}})

julia> @macroexpand Demo2.@NamedTuple {a::Foo}
:(Main.Demo2.NamedTuple{(:a,), Main.Demo2.Tuple{Main.Demo2.Foo}})

Maybe this'd be a nice test case?

@stevengj
Copy link
Member Author

stevengj commented Feb 1, 2020

win32 test failures seem unrelated (failure in cmdlineargs and downloading curl).

@stevengj stevengj added the triage This should be discussed on a triage call label Feb 1, 2020
@JeffBezanson JeffBezanson removed speculative Whether the change will be implemented is speculative triage This should be discussed on a triage call labels Feb 20, 2020
@JeffBezanson
Copy link
Member

👍 from triage.

@JeffBezanson JeffBezanson merged commit f5dbc47 into master Feb 21, 2020
@JeffBezanson JeffBezanson deleted the sgj/at-NamedTuple branch February 21, 2020 19:10
birm pushed a commit to birm/julia that referenced this pull request Feb 22, 2020
@stevengj stevengj added needs compat annotation Add !!! compat "Julia x.y" to the docstring and removed needs compat annotation Add !!! compat "Julia x.y" to the docstring labels Feb 25, 2020
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.

4 participants