Skip to content

Instantly share code, notes, and snippets.

@coquebg
Last active November 25, 2018 20:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coquebg/afe44e410f883a313dc849da3e1ff34c to your computer and use it in GitHub Desktop.
Save coquebg/afe44e410f883a313dc849da3e1ff34c to your computer and use it in GitHub Desktop.
GO2: Block level checks

Rational

Proposition

I would like to propose a new language construction for block level checks, which can be useful im many situations One application can be error handling, but the construction is not limited to this only

The new keyword will be in the form:

until [condition] { check expression } else { expressions }

Where

  • check is optionnal - if not specified, confition will not be evaluated; This has some drawbacks, as leaves responsibility to developer, but will not degrade performance with unnecessary evalutioans of condition;

    On first check, where condition evaluate to false, the execution will continue with the first expression after the block

  • else is optional (as with if construction) - if not specified, the execution will continue with the first expression after the block;

The construction is similar to try-catch construction in other languages, but it's not limited to error handling only.

Pros

  • More dense code
  • Code flow is easy to understand (no bouncing between handlers)
  • Construction is generic enough to be used for all kinds of checks
  • Constructions can be nested is nested ifs (IMHO this is bad design)

Cons

  • Additional level of nesting (more brackets...)
  • As check is optional, developer may forget to put it in a line, where required; Compiler may issue a error for lines, where variable, used in expression, is referensed (either as assignement or passsed as value) and no check keyword
  • For complex conditions, including several variables, all of them will be checked (even one of them is referensed in current line)

Examples

this is roughly equivalent to the following construction:

var v Variable
var check := func(){if !(condition_with_v) {goto ELSE} }
{
  v = expression_changes; check();
  goto END_BLOCK
  ELSE:
    // expressions_in_else_block
  END_BLOCK: // 
}

The condition will not be evaluated in declaration, but will be inserted after any expression with check keyword The else clause is optional and will be executed if condition evaluate to false - the code path will go to else block

This allow avoid repetitive if{} statements in the code for group of commands and improve readbility

Error handling can be expressed like this:

var err error
until err == nil {
   check value,err := someFunc() // condition is evaluated
   someFunc2(val)             // condition is not evaluated
   check item,err := value.GetItem(x) // condition is evaluated
} else {
   //handle error or ok (we can use **switch** construction here to check which part of condition is causing block interruption)
}

For more complex cases, the construction can be used with arbitrary checks that are evaluated to boolean Suppose we have settings structure with Valid() method, which performs various checks based on combination of settings

until s := &Settings{}; s.Valid(){
  check s.SetParam1(x)
  check s.SetParam2(y)
} else {
  return errors.New("Settings are not valid",s)
}