-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: reflect: add generic type arg info to reflect.Type #54393
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
Comments
I'm not sure |
@ianlancetaylor Those terms are not the ones I know from my youth. We used to talk about formals and actuals, which carry a distinct meaning already. Modern computing's use of the terms parameters and arguments results in a domain-specific redefinition of true synonyms in normal English. However, I admit that redefinition is not unique to Go. I wonder why this terminology shift happened. |
Adding methods to |
@icholy reflect.Type has unexported methods, so every type which implements it is in package reflect and can be updated along with the interface. Is there another sense in which it would be a breaking change to add methods to reflect.Type? |
@robpike That's true, now that you mention that I remember "formal" and "actual" as well. But today even the Go spec speaks of "function parameters" and "function arguments". |
FWIW I also learned "formal parameters" in school but have tended to use "parameter" and "argument" in my writing for at least the last decade or so because that seems (anecdotally) to be the current familiar jargon across various different language specs and tutorials. It is unfortunate that in plain English "parameter" and "argument" are not clearly differentiated in the way that is intended in this context, but that seems to be a common characteristic of plain words adopted as jargon. The dictionary tells me that "formal" as a noun means "an evening gown" and that "actual" isn't a noun at all, so those words don't seem to be obviously better cognates. I think it's beneficial to go with the flow here and use terms that people are likely to have encountered in other languages and in tutorials. (even though this sort of jargon evolution does make me notice my age.) With the obvious caveat that Wikipedia is a tertiary source rather than an authority, I do note that Parameter (computer programming) mentions both pairs of terms, but gives priority to "parameter" and "argument" while relegating "formal argument" and "actual argument" to secondary position. With that said, the section Parameters and Arguments does go on to acknowledge the inconsistency of usage and potential confusion between them. Interestingly, one of the first tutorials I found when looking for examples -- the "Functions" section of A Tour Of Go -- seems at first read to be using these terms without defining them and switching somewhat carelessly from one to the other without explaining their relationship:
As a reader who already knows the common meanings of "arguments" vs. "parameters" I probably wouldn't noticed this if I wasn't explicitly looking for examples. Perhaps what we can learn from this example is that the terms "argument" and "parameters" are so familiar to programming language learners that explicit definition and distinguishing remarks felt unnecessary here. (I'm assuming that a non-trivial number of people have successfully learned Go in part by following this tour.) |
Seems about the same difference between variables and values to me. |
Happy to switch this proposal to TypeArgument, TypeArg or even TypeActual. What do people prefer? Does the proposal otherwise sound reasonable? |
It should probably be
|
I've changed this proposal to use |
@aaronc |
Updated |
Note that if you have a local defined type declared within a type-parameterized function, then that function's type parameters are also implicit type parameters of the defined type. For example:
then |
Is there any chance this issue will be revisited? |
@jonbodner This proposal remains on the incoming queue. |
BTW, the "formal" vs "actual" parameter terminology dates (as so many things do) from ALGOL, and is still widely used in academic work, but a wide variety of language communities seem to have standardized on the "parameter"/"argument" terminology. |
This looks like a good proposal and no criticism has been given against it. Can this proposal be moved to the next phase? |
We spent a bunch of time discussing the surface API shape, and it seems that landed in a good place where there's consensus. However, we haven't yet discussed implementation tradeoffs. I'm far from an expert on this topic and so hopefully someone will correct me if I'm wrong on this 🤞 but I believe that currently only the compiler actually tracks the individual arguments for an instantiated generic type, while the final compiled program only has the string that's returned by That would mean that we'd also need to change the type information data structures to somehow track the type parameters in a way that allows recovering suitable Perhaps that means expanding Perhaps we could get extra fancy and add a new flag to Could the toolchain test whether there's any potential call to My intent in all of the above is to try to consider the cost of accepting this proposal for programs that would not actually use it, since I assume that only a small number of total Go programs need to inspect generic type parameters at runtime:
|
My previous comment was trying to understand the cost of accepting this proposal. I also note that this issue doesn't include much discussion of the benefit of accepting the proposal. What kind of program needs to be able to inspect the type information for generic type arguments at runtime? I have previously written code1 where it was useful to dynamically detect a type argument for one specific generic type, but that's already possible to solve in at least two different ways today, depending on how much information you have at compile time: type Example[T any] struct {
Value T
}
func exampleArgType[T any](v Example[T]) reflect.Type {
return reflect.TypeOf(T)
} type Example[T any] interface {
DoThing(T)
}
// exampleArgType takes a value whose dynamic type implements
// some instantiation of Example[T] and returns which T it implements
// it with. Results are unspecified if the given value does not implement
// any instantiation of Example[T].
func exampleArgType(v any) reflect.Type {
outer := reflect.TypeOf(v)
method := outer.MethodByName("DoThing")
return method.Type.In(0)
} It seems like this proposal would only be needed for situations where the program using this API knows nothing at all about the types it's going to be working with at runtime. Can anyone share concrete examples of such programs that would be useful to be able to write? Footnotes |
I'm not sure if this has been discussed already (I couldn't find a prior issue), but currently
reflect.Type
has no direct methods to retrieve the type arguments of generic types.The only way to retrieve these type arguments is by parsing the string returned by
Type.Name()
which includes fully qualified package names and could look something like this in a complex case:MyGenericType[some/package.Foo, map[string]other/package.Bar]
. This string is not easy to parse because of the possibility of nested type arguments, maps, slices, etc.I propose adding methods to
reflect.Type
to retrieve these type arguments programmatically:The text was updated successfully, but these errors were encountered: