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: Go 2: apply type redefinition recursively #23246

Closed
sougou opened this issue Dec 26, 2017 · 6 comments
Closed

proposal: Go 2: apply type redefinition recursively #23246

sougou opened this issue Dec 26, 2017 · 6 comments
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Milestone

Comments

@sougou
Copy link
Contributor

sougou commented Dec 26, 2017

If you have a recursive type like a LinkList:

type LinkList struct {
  Item interface{}
  Next *LinkList
}

Then a new type based on LinkList:

type LinkList2 LinkList

should expand to:

type LinkList2 struct {
  Item interface{}
  Next *LinkList2
}

This change by itself is not very useful. However, if we also allowed casting of LinkList2 to LinkList, it will allow methods of LinkeList2 to reuse methods of LinkList.

Obviously, we should consider this only if it doesn't break other parts of the language.

@gopherbot gopherbot added this to the Proposal milestone Dec 26, 2017
@pciet
Copy link
Contributor

pciet commented Dec 27, 2017

Do you have an example use case you’ve faced, and an example implementation using this feature?

// with Go 1
type LinkList2 container.LinkList

func (my LinkList2) FilteredAdd(item interface{}) {
    // the proposed feature removes these two casts?
    if LinkList2(my.Next).Filter(item) == false {
        container.LinkList(my).PushBack(item)
    }
}

func (my LinkList2) Filter(item interface{}) bool {
...

@sougou
Copy link
Contributor Author

sougou commented Dec 27, 2017

Here is an example that doesn't compile with Go 1:

package main

import (
	"fmt"
)

type LinkList struct {
	Item interface{}
	Next *LinkList
}

type LinkList2 LinkList

func (ll2 *LinkList2) Val() int {
	return ll2.Item.(int)
}

func main() {
	ll2 := &LinkList2{1, &LinkList2{2, nil}} // cannot use LinkList2 literal (type *LinkList2) as type *LinkList in field value
	for ll2 != nil {
		fmt.Printf("%d\n", ll2.Val())
		ll2 = ll2.Next // cannot use ll2.Next (type *LinkList) as type *LinkList2 in assignment
	}
}

Wrapping container.List is probably not a good use case because it doesn't expose its internal next member.

I previously needed this because I had a tree structure that had some basic traversal functions, and I wanted to build upon it by extending the type. However, that design has changed enough that I don't need this feature any more.

But I remembered that this would have made a few things convenient at that time. So, maybe others could benefit.

@sougou
Copy link
Contributor Author

sougou commented Dec 27, 2017

Playing my own devil's advocate. This proposal doesn't extend well for higher depths:

type A struct {
  BMember *B
}

type B struct {
  AMember *A
}

And a murkier variant:

type A struct {
  BMember *struct{
    AMember *A
  }
}

In the above cases, it becomes hard to come up with a good interpretation of type C A. So, I think the use case I presented is better solved by generics, if a consensus can be reached there.

I can close this issue unless I hear other thoughts.

@mvdan
Copy link
Member

mvdan commented Dec 27, 2017

I also agree that the rules for this feature in the language would either be simple yet flawed, or complicated.

As for the issue itself, I think it's ok to leave it open for Go2 so that it's not forgotten if and when a broader feature is designed, such as generics. It can always be closed at a later time.

@mvdan mvdan added v2 A language change or incompatible library change LanguageChange labels Dec 27, 2017
@pciet
Copy link
Contributor

pciet commented Dec 29, 2017

For a traversable tree of diverse types why not use an interface as the node type?

@ianlancetaylor
Copy link
Contributor

This is a step toward generic types. Let's take a full step instead of a small one. This is also not Go 1 compatible, but in a fairly subtle way.

@golang golang locked and limited conversation to collaborators Apr 17, 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

5 participants