Go: proposal: spec: support ... TODO statement

Created on 5 Nov 2019  ·  19Comments  ·  Source: golang/go

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.

FrozenDueToAge Go2 LanguageChange Proposal dotdotdot

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(...) 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.

All 19 comments

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.

Was this page helpful?
0 / 5 - 0 ratings