From a discussion with @griesemer and @ianlancetaylor, who have different opinions on this:
We could make Go support a ...
statement that compiles but fails at runtime, as if you wrote, say, panic("TODO")
.
Like https://docs.perl6.org/routine/....html
So sample code in space-constrained slides can say func (m *Method) Foo() { ... }
and be valid, but mostly so work-in-progress code during development compiles with ...
, instead of having to write panic("TODO")
.
cmd/vet
could perhaps fail if any exist in your program, to limit its spread (and prevent it from getting checked in).
It'd be a terminating statement.
In Perl6/Raku, it has to be the only statement in a block it seems.
Would it be possible to provide an example, sorry?
Would it be possible to provide an example, sorry?
type R struct {}
func (r *R) Read(p []byte) (n int, err error) { ... }
You'd have to make sure 'go vet' allowed it and 'cmd/vet' didn't, which is weird.
You'd have to make sure 'go vet' allowed it and 'cmd/vet' didn't, which is weird.
Not sure I follow.
The point is to make go test
fail if you have a ...
statement anywhere in your package. I just assumed vet would be a means to do that. IIRC, the vet checks done by go test already did/do differ from running vet manually.
If go test
fails with a ...
anywhere, I could never use this feature, as I develop by running go test
. I suspect many others are in this situation.
I admire the desire for a way to block out stuff for now, but I don't want that to preclude me testing other parts of the code.
One way to look at ...
is for it to mean "(compiler, please) fill in the blanks".
We already do this in array literals; e.g., in [...]int{1, 2, 3}
the ...
means "fill in the obvious array length" (which would be 3 in this case).
Generalizing this idea, len(...)
in a[len(...) - 1]
could mean "fill in the expression denoting the indexed array" (in this case of course a
would be shorter than ...
but in general that may not be the case). This has been mentioned in #33359 .
Furthermore, ...
in make(...)
and new(...)
could mean "fill in the type per context". For instance, one might be able to write:
var m map[string]float64
m = make(...) // make a map of m's type
See also #34515.
...
is also discussed in conjunction with return
statements where a return
of the form return ..., err
would also mean, "fill in the leading result expressions with the appropriate zero values".
See #21182.
With this general interpretation, ...
as a statement would mean "fill in the (obvious) statement" - which there isn't one, so at runtime we get a panic.
It could allow us to compile/type-check incomplete pseudo code as it might be used in a presentation. It would also be quite useful when rapidly developing a new piece of code (where I currently stub out missing pieces with panic(0)
).
I'm not convinced this is a good idea yet, but it seems as if it could be reasonably generalized, it's relatively simple, and has interesting use cases. It seems intriguing, especially if the use cases read naturally and almost explain themselves.
Q: Would ...{}
mean, use the context-correct type for the composite literal? Not sure.
@griesemer yesterday I started a blog post about the meaning of _ and ... in Go, and how we should think about them in proposed language changes. You have just scooped most of the post, and better than me. :) Want to do _ next?
One additional piece is an observation from Rog that _ is an identifier and ... isn’t, which has implications for what proposals involve syntax changes. Another observation is that ... clearly means “do what I mean”/“fill this in for me” for array lengths, but less obviously so for variadic function signatures or call sites.
With this general interpretation, ... as a statement would mean "fill in the (obvious) statement" - which there isn't one, so at runtime we get a panic.
If the compiler could not fill in an obvious statement, I’d expect compilation to fail, not a runtime panic.
@robpike,
If go test fails with a ... anywhere, I could never use this feature, as I develop by running go test. I suspect many others are in this situation.
I also develop by running go test as I wrote. But go test can return multiple failures at once: I can watch my tests start to pass, while also getting a vet failure.
If go vet
fails, tests don't run.
@bradfitz What's the advantage of using ...
for this purpose, rather than panic("TODO")
which works today and is more explicit? Just saving a few characters?
You propose that go vet
could treat it specially, but presumably go vet
could just as easily be made to recognize panic ("TODO")
.
What's the advantage of using ... for this purpose, rather than panic("TODO") which works today and is more explicit? Just saving a few characters?
That's basically it. This came out of a conversation about how Go uses ...
today and where we might use it more in the future. (@griesemer explained above)
While the idea is intriguing, I think that panic("TODO")
is much more clear, especially to a beginner, as to what happens if you were to call the function
This use of ...
feels different than the others proposed. All of the others mean "fill in the logical thing here", but it's not clear to me that this is the logical thing.
It also doesn't feel especially in tune with a language that doesn't allow you to have an unused variable.
If it is a good idea to have something like this, I'd prefer a builtin like todo()
which isn't much more to write but is much clearer to read (and easier to grep for allowing a hook to prevent such code from being committed). You could also fake it in earlier versions of Go with func todo() { panic("TODO") }
.
@griesemer as far as ...{}
, I don't see why that's any clearer than just having {}
especially when there are cases when the latter is allowed already.
Kotlin has a TODO() function in its standard library so that would be another option, though I'm not sure what package to put it in.
To be honest though I can't see what's wrong with panic("TODO")
. I certainly prefer it to ...
All of the others mean "fill in the logical thing here", but it's not clear to me that this is the logical thing.
Wandering off into semantics, I don't think it's exactly "fill in the logical thing". It's more like just "fill it in". If there's no logical thing to fill in, a Schelling point also works. That said, I'm also in the "just use panic("TODO")
" camp. (Although past me apparently decided to spell it panic("not implemented")
.)
Kotlin has a TODO() function in its standard library
Well, the same way Kotlin has it, we can probably just add a library function todo()
(akin to panic()
) and not mangle "..." use for this particular case? (The signature would probably be something like panic
's one too.)
That said, I do like the @griesemer proposal though about "..." being equivalent to "fill the dots" for the compiler
var m [] map[string]float64
m = make(..., 10) // make a slice of maps, preallocate 10 elements
because typing that stuff in obvious places is not fun. (sorry, my 2¢ to repaint the bike shed)
This is interesting thing, todo() looks great.
I'll retract this proposal. It was mostly there for completeness.
I've labeled all these issues with the dotdotdot
label for easier searching in the future.
Most helpful comment
One way to look at
...
is for it to mean "(compiler, please) fill in the blanks".We already do this in array literals; e.g., in
[...]int{1, 2, 3}
the...
means "fill in the obvious array length" (which would be 3 in this case).Generalizing this idea,
len(...)
ina[len(...) - 1]
could mean "fill in the expression denoting the indexed array" (in this case of coursea
would be shorter than...
but in general that may not be the case). This has been mentioned in #33359 .Furthermore,
...
inmake(...)
andnew(...)
could mean "fill in the type per context". For instance, one might be able to write:See also #34515.
...
is also discussed in conjunction withreturn
statements where areturn
of the formreturn ..., err
would also mean, "fill in the leading result expressions with the appropriate zero values".See #21182.
With this general interpretation,
...
as a statement would mean "fill in the (obvious) statement" - which there isn't one, so at runtime we get a panic.It could allow us to compile/type-check incomplete pseudo code as it might be used in a presentation. It would also be quite useful when rapidly developing a new piece of code (where I currently stub out missing pieces with
panic(0)
).I'm not convinced this is a good idea yet, but it seems as if it could be reasonably generalized, it's relatively simple, and has interesting use cases. It seems intriguing, especially if the use cases read naturally and almost explain themselves.
Q: Would
...{}
mean, use the context-correct type for the composite literal? Not sure.