Skip to content

default field values #10146

Description

@StefanKarpinski

This comes up periodically since people seem to expect it to work:

type Foo
    bar::Int=0
    baz::String=""
end

Currently, this doesn't do what people expect it to do at all, but I suspect we should change that. This would be a useful feature and the fact that so many people expect it seems like a pretty strong argument in its favor.

Activity

  1. johnmyleswhite commented on Feb 10, 2015

    @johnmyleswhite
    Member

    +1000

    I've often written macros to automatically give me both a type definition and an all-keywords constructor function with sane default values.

  2. ViralBShah commented on Feb 10, 2015

    @ViralBShah
    SponsorMember

    This certainly is a useful feature to have.

  3. ihnorton commented on Feb 10, 2015

    @ihnorton
    Member

    (ref #5790 #9443)

  4. tkelman commented on Feb 10, 2015

    @tkelman
    Contributor

    same thought recently #6122 (comment)

    If breaking the current semantics of how = inside a type definition works would somehow be a major problem, then maybe we could use different syntax for this - I think => inside a type definition would currently be invalid?

  5. StefanKarpinski commented on Feb 10, 2015

    @StefanKarpinski
    SponsorMemberAuthor

    No, I think we should just bite the bullet and change it. Very little code would get broken. This is used once or twice in base and probably very few other places.

  6. JeffBezanson commented on Feb 10, 2015

    @JeffBezanson
    SponsorMember

    I agree we should just change it.

  7. jakebolewski commented on Feb 10, 2015

    @jakebolewski
    Member

    Doesn't this complicate the semantics of inner constructors even more? The distinction between inner and outer constructors is a tricky concept to explain to people unfamiliar with the language.

    How does this interact with evaluating arbitrary expressions for type fields?

    type Foo
        foo::Int=rand(1:10)
        baz::String=randstring()
    end

    I feel allowing side-effects here is a bit weird.

  8. JeffBezanson commented on Feb 10, 2015

    @JeffBezanson
    SponsorMember

    I assume this would only work for default constructors.

  9. jakebolewski commented on Feb 10, 2015

    @jakebolewski
    Member

    So the following would retain the behavior we have now (expressions would be ignored)?

    type Foo
        foo::Int=rand(1:10)
        baz::String=randstring()
    
        Foo() = new()
        Foo(f) = new(f)
    end
  10. aviks commented on Feb 10, 2015

    @aviks
    Member

    Given that the inner/outer constructor business is one of the most complicated parts of the (otherwise reasonably simple) language, I wonder if this is worth the increased complexity?

    Wouldn't documenting the pattern of creating a no-arg inner constructor suffice?

  11. johnmyleswhite commented on Feb 10, 2015

    @johnmyleswhite
    Member

    Wouldn't documenting the pattern of creating a no-arg inner constructor suffice?

    I'd argue that the no-arg constructor (which shouldn't be the inner constructor, but only one outer constructor) is an anti-pattern.

  12. StefanKarpinski commented on Feb 10, 2015

    @StefanKarpinski
    SponsorMemberAuthor

    Why not use defaults in new for all arguments that aren't provided? This would work very well with new with keywords since you can provide whatever subset of values you want to and get defaults for the rest. Keep in mind that if you're going to add a language feature, you might as well make it powerful.

  13. johnmyleswhite commented on Feb 10, 2015

    @johnmyleswhite
    Member

    I'm assuming that the use of keywords in new will slow down construction of types even when you don't use keyword arguments, which seems like a large risk.

  14. 55 remaining items

  15. cstjean commented on Jun 27, 2017

    @cstjean
    Contributor

    it feels like GaussianVariogram{Float64}() should work, which is not something Parameters.jl can do IIRC.

    It does:

    julia> using Parameters
    
    julia> @with_kw struct Blag{T}
              x::T=one(T)
              y::T=one(T)
           end
    Blag
    
    julia> Blag{Float64}()
    Blag{Float64}
      x: Float64 1.0
      y: Float64 1.0
  16. ChrisRackauckas commented on Jun 27, 2017

    @ChrisRackauckas
    Member

    Wow cool, never knew that. Though it does have the lack of inferrability:

    julia> @with_kw struct Blag{T}
                     x::T=one(T)
                     y::T=one(T)
                  end
    Blag
    
    julia> @code_warntype Blag{Float64}()
    Variables:
      #self#::Type{Blag{Float64}}
    
    Body:
      begin
          return ((Core.getfield)($(QuoteNode(Core.Box(#call#1))), :contents)::Any)((Base.sitofp)(Float64, 1)::Float64, (Base.sitofp)(Float64, 1)::Float64, #self#::Type{Blag{Float64}})::Any
      end::Any
  17. juliohm commented on Jun 27, 2017

    @juliohm
    Contributor

    It doesn't for me:

    using Parameters
    
    @with_kw immutable Foo{T<:Real}
      a::T = one(T)
    end
    
    Foo()

    EDIT:
    Got it, you have to be explicit about the type in order for it to work.

  18. mauro3 commented on Jun 27, 2017

    @mauro3
    Contributor

    @StefanKarpinski: I assumed that this issue would be solved by automatically generating a keyword constructor rather than modifying new. But your approach maybe easier.

    For below type this would mean

    struct A
      a
      b=5
    end

    What would new's signatures be? You suggest, I think:

    new(a, b) = ...
    new(a; b=5) = ...
    new(;a=undef, b=5) = ...

    with the automatically defined inner constructors:

    A(a,b) = new(a,b)
    A(;kws...) = new(;kws...)
  19. modified the milestones: , on Jul 7, 2017
  20. StefanKarpinski commented on Jul 7, 2017

    @StefanKarpinski
    SponsorMemberAuthor

    I'm changing the milestone to 1.x since this seems like a feature that we can add post 1.0 as long as we've made the appropriate things errors in advance.

  21. pkofod commented on Mar 5, 2018

    @pkofod
    Contributor

    as long as we've made the appropriate things errors in advance.

    Is it clear if the appropriate things error in the current state of master, or if something needs to be prepared for this to be simple to do post v1.0?

  22. StefanKarpinski commented on Mar 5, 2018

    @StefanKarpinski
    SponsorMemberAuthor

    It's a syntax error now, so we're all good:

    julia> struct Foo
               a::Int = 0
           end
    ERROR: syntax: "a::Int = 0" inside type definition is reserved
  23. juliohm commented on Aug 15, 2019

    @juliohm
    Contributor

    Could default field values be part of Julia v1.3? I wonder if we can also have the @unpack functionality from Parameters.jl as well.

  24. StefanKarpinski commented on Aug 15, 2019

    @StefanKarpinski
    SponsorMemberAuthor

    Since the feature freeze is today, no. But if someone implements it in the next four months, it could be in the 1.4 release.

  25. Nosferican commented on Jul 25, 2020

    @Nosferican
    Contributor

    For v1.6?

  26. removed this from the milestone on Mar 13, 2022
  27. kdheepak commented on Nov 30, 2024

    @kdheepak
    Contributor

    I believe this issue shouldn't have been closed? Since a non-macro solution is possible in the future.

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

Metadata

Metadata

Assignees

Labels

speculativeWhether the change will be implemented is speculative

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions