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

proposal: spec: replace &T{} composite literals with (*T){} #20447

Closed
alercah opened this issue May 22, 2017 · 13 comments
Closed

proposal: spec: replace &T{} composite literals with (*T){} #20447

alercah opened this issue May 22, 2017 · 13 comments
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Milestone

Comments

@alercah
Copy link

alercah commented May 22, 2017

The use of &T{} for composite literals is strange, and in particular inconsistent with the way you write a type. Consider the following code:

foo := struct{
  m map[int]string
  a [10]int
  sl []string
  st struct{} 
  p *struct{}
}{
  m: map[int]string{},
  a: [10]int{},
  sl: []string{},
  st: struct{},
  p: &struct{},
}

p is the only member for which the type declared does not match the type used in the composite literal. The logical fix is to make a composite literal of type *T mean a composite literal to a pointer to a new value of type T initialized from the literal, in place of &T.

This is probably incompatible with #20446.

@gopherbot gopherbot added this to the Proposal milestone May 22, 2017
@cznic
Copy link
Contributor

cznic commented May 22, 2017

foo := struct{
        p *int
}{
        p: &i,
}

@mattn
Copy link
Member

mattn commented May 22, 2017

&T have two meanings.

  • create value T from literal
  • and get address of the value

If want to create new int value and get pointer of the value, we can't do it without new builtin. (ex: new(int)) If you mean a := *int or a := *int{} should have meaning to get pointer of new value, compiler will have to look backward literals like C. Then compiler will be slow.

@mvdan mvdan added v2 A language change or incompatible library change LanguageChange labels May 22, 2017
@aarzilli
Copy link
Contributor

But then what's the dereference operator? I think the most logical thing would be to use & in the type signature of pointers, so that if you have a var i int then &i's type is &int and the type signature and literal expression also match. And there is a historical precedent (in C++) for &T being a pointer to T.

But I don't think it's worth it.

@henryas
Copy link

henryas commented May 22, 2017

If you are to replace &T{} with *T{}, I would be confused. I am used to seeing the pointer/deref (*) and the address of (&) operators. I think Go's usage of them has been consistent with other C-family programming languages. If you are to replace those, you will create unnecessary confusion to many people, considering the popularity of C/C++ and the people's familiarity with them.

I don't agree with this proposal.

@bcmills
Copy link
Contributor

bcmills commented May 22, 2017

Note that in your example, the lines

  st: struct{},
  p: &struct{},

must today be written as

  st: struct{}{},
  p: &struct{}{},

(two pairs of braces each).

I suspect that, to avoid a parsing ambiguity, the latter case would need to be written as

  p: (*struct{}){},

but today that syntax is rejected by the compiler (https://play.golang.org/p/6GxjWrCfgN).

@bcmills
Copy link
Contributor

bcmills commented May 22, 2017

Also note that under #12854 they could be written even more uniformly:

foo := struct{
  m map[int]string
  a [10]int
  sl []string
  st struct{} 
  p *struct{}
}{
  m:  {},
  a:  {},
  sl: {},
  st: {},
  p:  {},
}

@ianlancetaylor
Copy link
Contributor

This idea was discussed during the development of Go 1 (that is, as a change from the earlier versions of Go to the standarized Go 1), but was rejected at that time.

@andlabs
Copy link
Contributor

andlabs commented Jun 7, 2017

It is important to understand that & and * aren't interchangeable tokens, but rather opposite and complementary. & means "take the address of value", and * means "get the value at address". From this, it makes no logical sense to say *T{}, because you would wind up reading this as "take the value at the address T{}", and then you realize T{} isn't an address and so the statement makes no sense.

Perhaps memorizing this would help you stop confusing &T{} and *T{} as much (as you said in the proposal for #20446).

This also explains @cznic's comment: what if you want to point to a variable that already exists in a composite literal? (The line that is missing from their comment is var i int.)

@bcmills
Copy link
Contributor

bcmills commented Jun 7, 2017

@andlabs The * operator is distinct from the * type-constructor. The & operator is dual to the * operator, but the * type-constructor has no dual.

&T{} is the expression "address of a literal of type T", but *T is the type "pointer to T". The * operator is not involved in this proposal in any visible way.

@andlabs
Copy link
Contributor

andlabs commented Jun 7, 2017

@bcmills Yes, but is &T{} in the context of an assignment or composite literal also not an expression? Given what you said, another way to say what I was trying to say is that this proposal confuses and conflates the * type-constructor with the * operator, if that makes more sense.

@bcmills
Copy link
Contributor

bcmills commented Jun 7, 2017

The way I read this proposal, it is that &T{} should be read as "the address of a literal of type T", and *T{} should be read as "a literal of type *T". (The latter is currently rejected as a syntax error.)

@andlabs
Copy link
Contributor

andlabs commented Jun 7, 2017

Ah, yes, that is different. If we do expand composite literals to all types (a more general version of your reading of the proposal), by current rules it would have to be (*T){...}.

Isn't the current situation due to ambiguity between the binary * operator? A potential solution would be to drop * for indirection, but that seems to be beyond the scope of the current proposal phase for Go 2?

@rsc rsc changed the title proposal: Go 2: Replace &T{} composite literals with *T{}. proposal: spec: replace &T{} composite literals with (*T){} Jun 16, 2017
@rsc rsc changed the title proposal: spec: replace &T{} composite literals with (*T){} proposal: spec: replace &T{} composite literals with (*T){} Jun 16, 2017
@ianlancetaylor
Copy link
Contributor

There doesn't appear to be strong support for this, and you say yourself it would be incompatible with #20446 / #9097. It was also discussed years ago and rejected. Closing.

@golang golang locked and limited conversation to collaborators Feb 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

10 participants