Flow Control
Branching and flow control tends to be the most difficult follow - in fact the only other is linear code which is easy. So minimizing the ways that branching can happen makes code easier to maintain.
An observation of Go that I like is that indentation naturally shows branching. Function definitions are left align. Linear logic is indented once and branches are indented twice.
For
I like that Go has a single loop.
It really follows 4 forms:
- Infinite
- While(bool)
- for(init;bool;after)
- foreach
What I'd like to do is replace all of these with a single iterator interface.
Single Statement
An extreme option, but interesting - only allow a single statement inside a for loop. This prevents deeply nested loops. With compiler in-lining, there's no cost.
The counter argument is that a loop may be manipulating a lot of variables, but in that case it's not hard to create a struct with a method for the inner loop.
Return
From a function.
One piece of syntactic sugar I'm considering is a conditional return. To keep the right aligned thing, I think this would be indented twice.
foo.Err? => return foo
If
Not much here.
Except the same thing as return. Possibly allow a one liner but only when the if is calling a function or method. I was tempted to say a single statement, but assignments would be hard to read
foo.Foo? => foo.DoFoo() // hard to read foo.Foo? => foo.BarIdx = foo.next[foo.BarIdx-1]
Ternary Expression
I often miss ternary statements in Go, but they are ripe for abuse. I think placing some extreme restrictions on them would balance this. The whole thing must be immutible. The two values must be terminals expressions (literals or function calls)
x = (x > 0) ? x : 0
Though the hyper-consistent part of me wants to make it list index based:
x = (x, 0)[x > 0]
Switch
Again, hyper-consistent is tempted. This can be done with map
{
20:
return foo
55:
return "schfifty fiv"
3:
return "3.1415"
}[foo.bar]
But this does have a few issues. There's no default, this could be added to Map. The key is at the end - but perhaps it should be at the start everywhere. It requires a value type of CodeBlock, but again, this may be useful.