-
Notifications
You must be signed in to change notification settings - Fork 17.6k
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: Uniform Function Call Syntax #56242
Comments
Lua allows something like this with the a:foo syntax getting rewritten to a.foo(a) , but I am not sure if it is a good idea for Go. |
If I'm reading this correctly, what about code like type S struct {}
func (S) F() {}
func F(S) {}
func G(a S) {
a.F() // Does this call F or S.F?
} That is, Of course we can make a rule for this case (and we would have to that it calls |
In the case of ambiguity like this, I would expect the method to match prior to the function, and therefor be the selected callee. That is, a.F() should call the method S.F with a as the receiver. From the proposal:
My rationale is that a method is part of the type's design, whereas functions are not. I can see other expectations being reasonable as well, and if an alternative matching were selected, I'd be okay with it. From my perspective, the most important thing is that the resolution of this ambiguity is deterministic and fairly easy to predict. There is admittedly the issue that one could write a set of generic functions that end up calling a method when they are expecting to call a function:
This may or may not be a problem. A generic library might make effective use of this by treating the function/method name as an interface hook - sort of a simple analog to the curiously recurring template pattern in C++ (https://en.cppreference.com/w/cpp/language/crtp). |
Copying over from #56283 (TBQH these should really be duplicates): Under this proposal,
I think this ambiguity, even if we can resolve it in the spec, makes code harder to understand. There's also a parsing ambiguity, in that |
Hey @earlye - I just had these conversations that you are having in this issue - #49085. I accepted that using the |
@Merovius - I think #56283 probably is a duplicate, though I haven't read closely enough to confirm. Will try to make some time to do so. I see your point, along with @asegs ' point about ambiguity. But I think it's important to note that 1 and 2 are indistinguishable without more context today. Specifically, the context of whether Given the proposal's rule that we attempt to match methods before functions, I believe 3 vs 4 is the more problematic ambiguity: is I think this is the situation where a new operator would resolve the ambiguity fairly easily:
You could refine the proposal to say that "if the caller wants UFCS lookup, they use the new operator NOTE: I chose |
This is again exactly where I ended up, check out my proposal and feel free to discuss there. |
@Merovius I think your example is actually a little bit worse, given expression
but if B is a package name it will parse to
which means that go/parser.ParseExpr has to be deprecated because parsing a standalone expression is now impossible without the list of package names. If we want this syntax to be backwards compatible, i.e. |
@aarzilli I think That being said, I believe there is a consensus that using |
Or introduce |
This introduces a new way to do something that we can already do. It also introduces an ambiguity between whether The emoji voting is also fairly negative. For these reasons, this is a likely decline. Leaving open for four weeks for final comments. |
While I personally like UCS a lot, I think that it cannot make it to Go for one simple reason - age. Go is a mature language, well past v 1.0 and any such change will not only bring questions about backwards compatibility, but what is more important - as @ianlancetaylor pointed out, it will cause confusion with methods and will lead to a lot of potential code inconsistency. Let's not even mention the impact on the build tool ecosystem (linters, static analysis tools) - judging by how much it has been taking those to adopt generics, we don't want to introduce another potential seismic shift. That said, UCS is awesome and I definitely encourage everyone to have a look at how it has been implemented in other languages. I personally am on the controversial opinion that Go could have lived just as well without the method syntax - and UCS could have been a perfect solution for adding a bit of OO syntactic sugar to Go. But that train has long since gone. Plus, I have no idea how one would have tackled interfaces and polymorphism without methods. |
No change in consensus. |
Author background
Related proposals
Proposal
Use Uniform Function Call Syntax to allow the first parameter to any function, suffixed by a '.', to be placed to the left of the qualified function name.
Examples:
My personal motivation is that I would like to allow my generic code to support function chaining like we see in other languages:
A clause saying that it is possible for the right-hand side of a
.
to be a (possibly generic) function specifier, in which case that function would be called, passing in the left-hand side of the.
as the first parameter to the specified function. If there is ambiguity because the function specifier matches both a method and a function, I believe the method should be preferred.You can call functions as if they are methods, provided the function takes as its first parameter, the type of thing that is to the left of the
.
.Is this change backward compatible?
How backwards compatible?
This change should not break any existing code, since method invocations would be preferred over UFCS invocations. It is essentially an expansion of the syntax.
Orthogonality: how does this change interact or overlap with existing features?
I've mentioned how it interacts with generics. I suspect it would also interact with the ability to extend interfaces in multiple modules, in the sense that you can effectively add (namespaced) method-like functions to any type.
Not exactly. It's more a development quality-of-life improvement.
Costs
Would this change make Go easier or harder to learn, and why?
I personally would find it to be a wash.
What is the cost of this proposal? (Every language change has a cost).
How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
I don't understand the golang codebase enough to quantify these questions.
What is the compile time cost?
I suspect it's fairly minimal, but again, I haven't delved too deeply into the golang codebase.
What is the run time cost?
0, since this is just syntactic sugar.
Can you describe a possible implementation?
(I have no idea if this is feasible in the context of the current language's implementation)
When you've encountered what appears to be a method call, and the method specifier does not match any visible methods for the type to the left of the
.
, proceed to check if there are any functions that match the method specifier and take as the first parameter the same type as the item to the left of the.
. If such a match is made, treat it as a UFCS function call.Do you have a prototype? (This is not required.)
No. I wish I had time to learn the internals of Go well enough to build one.
The text was updated successfully, but these errors were encountered: