7 ms·
I'm glad that escape analysis now allows for more natural if/then control flow. But I'm still unhappy that using named return values still requires you to put
by taliesinb 14y ago
I'm glad that escape analysis now allows for more natural if/then control flow.
But I'm still unhappy that using named return values still requires you to put a superfluous "return;" at the end of such a function.
The whole reason I use named return values is to cut down on the boilerplate code that carries the return value around -- so why not cut out the final boilerplate 'return'? It doesn't solve any problem or add any information!
Otherwise, there are some nice improvements here. Other than the things mentioned so far, I'm glad to see reflection filling out -- the day a Go REPL will be possible is approaching.
- burntsushi 14y ago> Other than the things mentioned so far, I'm glad to see reflection filling out -- the day a Go REPL will be possible is approaching. Very close indeed! Struct, array and function types still can't be constructed at run time, but as of Go 1.1, function values can be as well as slice, map and channel types. I exploit some of this in my `ty` package. [1,2] [1] - http://godoc.org/github.com/BurntSushi/ty http://godoc.org/github.com/BurntSushi/ty [2] - http://blog.burntsushi.net/type-parametric-functions-golang http://blog.burntsushi.net/type-parametric-functions-golang
- taliesinb 13y agoThis is pretty cool! I tried to convince rsc at some point about the enormous value of REPLs for rapid development.. imagine connecting to an embedded REPL on a server to do live debugging. I don't think I quite convinced him to drop everything and do it himself, though. Do you have plans to experiment with a transpiler to smooth away all the remaining type noise? Maybe a first step would be to explore how one could add pluggable 'dialect translators' to the go tool so that anyone could write simple extensions for the language while preserving the existing toolchain.
- burntsushi 13y ago> Do you have plans to experiment with a transpiler to smooth away all the remaining type noise? I don't have any particular plans; the `ty` package was a night of hacking plus several days of polishing/writing. :-) One of the major bummers about moving into the reflection world is performance. My blog article talks about it a little bit, but it's also worth looking more closely at the things I didn't talk about in the benchmarks. (For instance, it seems that function calls in the reflection world pay a very steep price.) Re transpiler: do you mean a {Language}-to-Go source translation? If so, it seems like you'd want to avoid `reflect` completely in that case. But maybe I am misunderstanding. > I tried to convince rsc at some point about the enormous value of REPLs for rapid development ... I don't think I quite convinced him to drop everything and do it himself, though. A REPL would be very nice, but a REPL using `reflect` would definitely be a lot of work. You'd need to make extensive use of the sub-packages in `go` to convert the `Read` portion of the `REPL` into appropriate reflection types. You could do it now, but you wouldn't be able to define new functions, structs or interfaces. And `reflect` cannot spawn goroutines either, which is a bummer.
- pjmlp 13y ago> ... the day a Go REPL will be possible is approaching. A REPL is possible even today. All is needed is an interpreter for the language and there are a few already available. Nothing new, this is the same approach taken by many languages, provide an interactive environment for the REPL and a compiler for distribution. Being done since the early days of computing.
- TazeTSchnitzel 13y agoOr an incremental compiler.
- pjmlp 13y agoFor a REPL workflow it usually does not work, because most developers are trying out pieces of the application. When I work with ML or Lisp based languages, I am always copied code snippets, which might land in separate modules afterwards. Unless you mean a JIT at the REPL environment.
- blablabla123 14y agoJust a wild guess, not sure about the true reasons: it adds the information that the control flow can hit the end of the function and that it actually returns something. All that given the writer doesn't write syntactically superfluous returns. Also I slightly disagree with you that named return values are for short code. This may be true in functions that return at many points. For other functions it may need some otherwisely added boilerplate. If you write inside an if-block f, err := os.Open(...) that err is a different one than your return value err. So you would need to add var f *os.Open above the if to write f, err = os.Open(...). Having that said, IMHO the greatest pro of named return values is well understandable code, in particular for libraries.
- taliesinb 13y ago1. I'm not sure I understand. If a function shouldn't hit the end, put a panic there. If you want to emphasize that it does, put an explicit "return;" in. But requiring you to put in a "return;" yields no information at all. Dead code isn't an error. 2. You're right, they're not only for short code. That however is where the forced "return" is most glaring.
- davvid 13y agoI can see the benefit of the forced return, but only because it's bitten me in the past. In Python, if you don't say `return` the function returns `None`.
- laumars 13y agoThat's less of an issue for Go as aside interface{}, fundamental types can't be nil. Plus the instance we're talking about here is with named returns, so the variables are already initialised. From a personal perspective, I find having to include "return" a pain as there's times when it's completely unnecessary. eg in switch statements or if else where each condition has it's own return. While it's an easy fix for if else (just drop the else / default case), it makes the code look a little less pretty in my opinion.
- rsc 13y agoThe final return does add information. It is common to name return variables to make the meaning clear to prospective users, without using them in the body. Just to pick the first one I found, here is the definition for regexp.Match: // Match checks whether a textual regular expression // matches a byte slice. More complicated queries need // to use Compile and the full Regexp interface. func Match(pattern string, b []byte) (matched bool, error error) { re, err := Compile(pattern) if err != nil { return false, err } return re.Match(b), nil } If the final line is missing, the compiler rejects the function. You might well have meant 'return', which could be inserted implicitly, but you might also have been interrupted while writing the function and meant to write a 'return something'. The compiler (really the language) requires you to be clear to avoid inferring an incorrect completion. One nit: the return rules are separate from escape analysis, which is about keeping things on the stack instead of allocating them on the heap.
- taliesinb 13y ago1. Or maybe you were interrupted right after writing "return" :-). This one weird simple trick could work (and give you white teeth): implicit returns only get inserted if all the named return variables are assigned-to at least once in the body of the function. Perhaps that breaks your pure syntactic rule, though. 2. Yup, wrong term.