Case statement

Example:

  1. case readline(stdin)
  2. of "delete-everything", "restart-computer":
  3. echo "permission denied"
  4. of "go-for-a-walk": echo "please yourself"
  5. else: echo "unknown command"
  6. # indentation of the branches is also allowed; and so is an optional colon
  7. # after the selecting expression:
  8. case readline(stdin):
  9. of "delete-everything", "restart-computer":
  10. echo "permission denied"
  11. of "go-for-a-walk": echo "please yourself"
  12. else: echo "unknown command"

The case statement is similar to the if statement, but it represents a multi-branch selection. The expression after the keyword case is evaluated and if its value is in a slicelist the corresponding statements (after the of keyword) are executed. If the value is not in any given slicelist the else part is executed. If there is no else part and not all possible values that expr can hold occur in a slicelist, a static error occurs. This holds only for expressions of ordinal types. “All possible values” of expr are determined by expr’s type. To suppress the static error an else part with an empty discard statement should be used.

For non ordinal types it is not possible to list every possible value and so these always require an else part.

Because case statements are checked for exhaustiveness during semantic analysis, the value in every of branch must be a constant expression. This restriction also allows the compiler to generate more performant code.

As a special semantic extension, an expression in an of branch of a case statement may evaluate to a set or array constructor; the set or array is then expanded into a list of its elements:

  1. const
  2. SymChars: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
  3. proc classify(s: string) =
  4. case s[0]
  5. of SymChars, '_': echo "an identifier"
  6. of '0'..'9': echo "a number"
  7. else: echo "other"
  8. # is equivalent to:
  9. proc classify(s: string) =
  10. case s[0]
  11. of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': echo "an identifier"
  12. of '0'..'9': echo "a number"
  13. else: echo "other"

The case statement doesn’t produce an l-value, so the following example won’t work:

  1. type
  2. Foo = ref object
  3. x: seq[string]
  4. proc get_x(x: Foo): var seq[string] =
  5. # doesn't work
  6. case true
  7. of true:
  8. x.x
  9. else:
  10. x.x
  11. var foo = Foo(x: @[])
  12. foo.get_x().add("asd")

This can be fixed by explicitly using return:

  1. proc get_x(x: Foo): var seq[string] =
  2. case true
  3. of true:
  4. return x.x
  5. else:
  6. return x.x