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

Allow type declarations based on static type of variables or struct or interface elements #4626

Closed
gopherbot opened this issue Jan 7, 2013 · 3 comments

Comments

@gopherbot
Copy link

by RIrelan:

Go allows the static type of a newly declared-and-defined variable to be inferred from
the expression initializing the variable using the ":=" operator, as in

    a := 4  // Now "a" has type "int"
    b := a  // "b" also has type "int"

However, it is otherwise impossible to declare the static type of a variable, array
entry, or map key or value without hardcoding its type. Specifically, as described in
this Stack Overflow post
(http://stackoverflow.com/questions/14191043/get-static-type-of-struct-element/14191310#14191310),
I was writing a tool that determines the combined size of all the files under a
directory, like the `du -s` command, that remembers the inodes that it has visited so
that hard-linked files don't have their sizes counted twice. I intended to keep track of
the inodes using a map from the type of syscall.Stat_t.Ino (which is uint64) to a struct
defined as

    type ino_entry struct {
        st    *syscall.Stat_t
        nodes []string
    }

where `nodes` contains the names of all the files hard-linked to the inode.

However, to make this map, it's required to hardcode the type of syscall.Stat_t.Ino into
the declaration of the map, as in

    make(map [uint64] ino_entry)

whereas it might be useful to be able to declare this as

    make(map [typeof(syscall.Stat_t.Ino)] ino_entry)

where `typeof` would obtain the static type of a variable, struct member, or interface
member (I'm not so sure that this would be useful, since only functions may be declared
as parts of interfaces).

With this change, the following declarations would all become legal (given that `st` is
a variable of type `*syscall.Stat_t`):

    entmap := make(map [typeof(syscall.Stat_t.Ino)] ino_entry)  // Works on elements of a struct type
    var ino1 typeof(st.Ino)  // as well as elements of a struct variable
    ino1 = 0
    inoa := []typeof(ino1){0, 1, 2}
    inop := new(typeof(ino1))
    ino2 := *inop  // ino2 == ino
    for i, ino := range inoa {
        fmt.Printf("inoa[%v] = %v\n", i, ino)  // prints inoa[0] = 0, etc.
    }

    // We can assign to maps too
    for i := 0; i != len(inoa); i++ {
    entp := new(ino_entry)
    entmap[inoa[i]] = *entp
    }

In general, any function that today takes an argument of generic type (i.e., type T)
could obtain that type from typeof() as well.

Right now, as far as I can tell, the only way to avoid hardcoding the type in these
situations is to use reflection, whereas all of the above could be done statically. One
wrinkle that I can see is that it might be useful to access the static type of the keys
and values of a map, or that of the elements of an array or slice, separately from the
type of the map or slice as a whole, whereas there's no syntax for that right now in the
general case (although it's possible if you already have an index into the slice or map
using `typeof(my_slice[idx])`, `typeof(key)`, and `typeof(my_map[key])`). Also, the
syntax for this is just a suggestion, although I avoided `x.(type)` since that's already
associated with switching on the type of an interface.
@dsymonds
Copy link
Contributor

dsymonds commented Jan 8, 2013

Comment 1:

Labels changed: added priority-later, languagechange, removed priority-triage, go1.1.

@cznic
Copy link
Contributor

cznic commented Jan 18, 2013

Comment 3:

Go supports type inference based on the type of a value, but only where a value must
occur - in a variable initializer of a variable _declaration_. (`v := expr` === `var v T
= expr`, where T is type of `expr`). Struct fields don't allow initializing expressions
in the declaration. Seeing a name of a type field where a type lit or type name normaly
is, would be IMO strange.
If some kind of referring to a type by naming some existing entity should be adopted,
them IMO it have to be available everywhere, not only for struct fields.
Anyway, IMO this feature request, if adopted, makes more harm to the language than what
value it brings.
Is there a precedence in any other statically typed language providing something like
this? (Not a decision factor, would like to take a look on it)

@rsc
Copy link
Contributor

rsc commented Jan 31, 2013

Comment 4:

What you've proposed is exactly the GNU C typeof, and we've looked at this before.
Usually if you need typeof the API is broken and should be fixed.

Status changed to WontFix.

@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants