/union

Anonymous unions in Nim

Primary LanguageNimMIT LicenseMIT

An implementation of anonymous unions in Nim

CI status Minimum supported Nim version License

Example

import union

type None = object
  ## A type for not having any data

proc search[T, U](x: T, needle: U): union(U | None) =
  # Assignment can be done via explicit conversion
  result = None() as union(U | None)

  let idx = find(x, needle)
  if idx >= 0:
    # Or the `<-` operator which automatically converts the type
    result <- x[idx]

assert [1, 2, 42, 20, 1000].search(10) of None
assert [1, 2, 42, 20, 1000].search(42) as int == 42
# For `==`, no explicit conversion is necessary
assert [1, 2, 42, 20, 1000].search(42) == 42
# Types that are not active at the moment will simply be treated as not equal
assert [1, 2, 42, 20, 1000].search(1) != None()

proc `{}`[T](x: seq[T], idx: Natural): union(T | None) =
  ## An array accessor for seq[T] but doesn't raise if the index is not there
  # Using makeUnion, an expression may return more than one type
  makeUnion:
    if idx in 0 ..< x.len:
      x[idx]
    else:
      None()

assert @[1]{2} of None
assert @[42]{0} == 42

import json

# With unpack(), dispatching based on the union type at runtime is possible!
var x = 42 as union(int | string)

block:
  let j =
    unpack(x):
      # The unpacked variable name is `it` by default
      %it

  assert j.kind == JInt

x <- "string"

block:
  let j =
    # You can give the unpacked variable a different name via the second
    # parameter, too.
    unpack(x, upk):
      %upk

  assert j.kind == JString

See the documentation for more information on features and limitations of this module

License

This project is distributed under the terms of the MIT license.

See license.txt for more details.