-
Notifications
You must be signed in to change notification settings - Fork 18k
Correctly pass multiple return values as arguments to other functions #973
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 think this used to work. I also think the spec allows it. I'd have to check both. Owner changed to r...@golang.org. Status changed to Accepted. |
The text of "..." isn't crystal clear, but this is: As a special case, if the return parameters of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. No other special cases for function calls are allowed. Therefore, since Printf takes a string argument first, the program here is erroneous. It's debatable whether the spec admits Printf(multipleReturnValues()) or Println(multipleReturnValues) but I think the answer is still no and in any case that narrow case is not what the report is about. In short, addressing this requires a change to the spec. It should be clarified to prevent or perhaps admit even the narrower interpretation. Status changed to Thinking. |
I expected this to work as well. If this works: package main
import "fmt"
func Init(mode, revelPath, basePath string) (string, string, string) {
return mode, revelPath, basePath
}
func ParsePaths(importPath, srcPath string) (mode, revelPath, basePath string) {
mode = "prod"
revelPath = "/revel"
basePath = "/"
return
}
func main() {
fmt.Println(Init(ParsePaths("/import", "/src")))
} then it's logical that this does too: package main
import "fmt"
func Init(mode, revelPath, basePath string) (string, string, string) {
return mode, revelPath, basePath
}
func ParsePaths(importPath, srcPath string) (revelPath, basePath string) {
revelPath = "/revel"
basePath = "/"
return
}
func main() {
fmt.Println(Init("prod", ParsePaths("/import", "/src")))
} but it does not :( Can we make this work? |
To be clear: |
@brendensoares It's certainly not "logical" - it's up to the rules of the spec, and the spec doesn't allow it, which is why the compiler doesn't do it. Please move language discussions to golang-nuts not the issue tracker. Also, the time for language changes has passed long ago. Thanks. |
@griesemer sorry, but when exactly did the time for improving Golang pass? Perhaps "logical" is not the best word, but rather "pragmatic" in that it is reasonable to expect the binding of arguments to return values to work consistently no matter the location of the arguments in the function's signature. |
@brendensoares As Robert said, the issue tracker is not the place for this kind of discussion. We use the issue tracker for bug reports, proposal, tracking changes, and the like. Thanks. |
@brendensoares https://golang.org/doc/faq#language_changes . And, for the reference, at GopherCon 2014, Rob Pike made the comment explicitly: "The language is done". Also, you are making the assumption that your suggestion is an "improvement". That is far from certain. To be clear, the current rules were carefully thought out and are deliberate. You can be assured that we thought about your suggestion during the design of the language (between 2007 and 2009). If your suggestion were permitted, what about f(g(), h()) where both g and h return multiple values that happen to match the parameter list of f? Should probably be permitted as well. And then we should also allow things like: "a, b, c, d := f(), g()" otherwise we have another inconsistency. And so forth. Permitting this is of course possible, but it also opens the door for unexpected errors. For instance, the parameter lists of the functions may change in unexpected ways and the code may still work, hiding errors. So the pragmatic solution here is to allow a small set of rules that are reasonably safe, and not to allow everything that might be possible. But again, please move this discussion elsewhere. If you have a concrete proposal, please follow the proposal process: https://github.com/golang/proposal . Thanks. |
@griesemer thanks. I've posted to golang-dev and chatted on freenode #go-nuts to get some insight. Your comment above is by far the most help I've received so far into understanding the possible underlying reasons that this functionality was excluded. Any idea if what @robpike said regarding adding clarification to the spec ("It should be clarified to |
@brendensoares @robpike mentioned later: "Therefore the narrower case is explicitly permitted, but the general case is still not." Per the spec. So there's no reason to make any spec changes. If there's no concrete issue filed (proposal, or bug) it's unlikely that it will get any attention. We do make minor spec adjustments, either to clarify a situation which is not well documented, or to remove an inconsistency (one part of the spec says one thing, another part says something else). In extremely rare cases we loosen the spec (e.g., most recently we allowed the omission of the key type for elements of map composite literals if the key was a composite literal as well. This is not one of those cases. It's been fairly uncontroversial, the compilers all agree, and the spec seems reasonably clear. Hope that helps. And again, please move this discussion elsewhere if you are still not satisfied, or follow the proposal process. Thanks. |
by Erlan.Sergaziev:
The text was updated successfully, but these errors were encountered: