Flow Control

From Adam Colton
Jump to navigation Jump to search

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.