Skip to content

Conversation

@ararslan
Copy link
Member

@ararslan ararslan commented Jul 8, 2018

The existence of @kwdef predates the existence of required keyword arguments; before that, all keyword arguments needed a default value. So currently when no value is specified for a field in the type definition given to @kwdef, it's assigned a default value based on the field's type.

Now, with this change, any field not explicitly given a default becomes a required keyword argument in the resulting type constructor when using @kwdef. In doing this, we're also able to drop the requirement that the type's fields be typed, and that the type has fields at all. That is, we can now allow

@kwdef struct A
    a = 1
end

as well as

@kwdef struct A end

(though of course the latter case isn't particularly useful).

Lastly, this adds type assertions to the keyword arguments in the resulting constructor. That piece has been removed.

Fixes #27970.

@ararslan ararslan added the keyword arguments f(x; keyword=arguments) label Jul 8, 2018
@ararslan ararslan force-pushed the aa/kwdef-reqd branch 4 times, most recently from 9c97c0b to 1165849 Compare July 8, 2018 22:44
Copy link
Member

@simonbyrne simonbyrne left a comment

Choose a reason for hiding this comment

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

Seems like a good idea.

@JeffBezanson
Copy link
Member

this adds type assertions to the keyword arguments in the resulting constructor

I'm all in favor of the rest of the change, but I'm not sure about this one. Usually we generate constructors that accept any arguments and convert to the field types.

@ararslan
Copy link
Member Author

Okay I've removed that change.

indexed_deltas::Cuint
received_bytes::Csize_t
total_objects::Cuint = Cuint(0)
indexed_objects::Cuint = Cuint(0)
Copy link
Member

Choose a reason for hiding this comment

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

This should work if you just do = 0, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

It didn't until I removed the assertion that Jeff mentioned, so it does work now. I'd rather not go back through and change all of these to be less explicit though.

@simonbyrne
Copy link
Member

simonbyrne commented Jul 11, 2018

Maybe add an explicit test for the auto-conversion? e.g.

@test Test27970Typed(a=0x03) == Test27970Typed(3)

@ararslan
Copy link
Member Author

Suggested test has been added.

@ararslan

This comment has been minimized.

The existence of at-kwdef predates the existence of required keyword
arguments; before that, all keyword arguments needed a default value.
So currently when no value is specified for a field in the type
definition given to kwdef, it's assigned a default value based on the
field's type.

With this change, any field not explicitly given a default becomes a
required keyword argument in the resulting type constructor when using
kwdef. In doing this, we're also able to drop the requirement that the
type's fields be typed, and that the type has fields at all.
@ararslan
Copy link
Member Author

Anyone want to take another look?

@JeffBezanson JeffBezanson merged commit fa11dec into master Jul 13, 2018
@JeffBezanson JeffBezanson deleted the aa/kwdef-reqd branch July 13, 2018 06:19
@marius311
Copy link
Contributor

What do you guys think about, if the type is a mutable struct, then fields without default values which are not specified via keyword arguments remain undefined and can be set later?

@ararslan
Copy link
Member Author

IMO that seems a little finnicky and easy to forget that the behavior differs based on whether the type is mutable.

@simonbyrne
Copy link
Member

Also, "undefined" is a bit of weird edge case that we don't really want to encourage, or at the very least, we want to be explicit (hence the undef argument for array creation).

@marius311
Copy link
Contributor

marius311 commented Sep 23, 2018

easy to forget that the behavior differs based on whether the type is mutable.

Yea, that's true. What about an option, say,

julia> @kwdef allow_undef=true mutable struct Foo
   x=2
   y
end

julia> Foo()
Foo(2, #undef)

This could work for both mutable/immutable (although in the latter case is likely less useful). Granted this probably significantly increases the complexity of writing the macro.

or at the very least, we want to be explicit (hence the undef argument for array creation)

That's fair, although in this case AFAIK I can't explicitly leave a field undefined using any outer constructor, right? I suppose another solution for me would be to allow "setting" something as #undef from an outer constructor (which could potentially make writing the allow_undef=true version pretty trivial). Are there any thoughts on allowing this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

keyword arguments f(x; keyword=arguments)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants