Skip to content

Instantly share code, notes, and snippets.

@oprypin
Last active August 29, 2015 14:18
Show Gist options
  • Save oprypin/429f0889d1bc645a9c58 to your computer and use it in GitHub Desktop.
Save oprypin/429f0889d1bc645a9c58 to your computer and use it in GitHub Desktop.
Option[T]
type
Nullable = concept x
isNil(x) is bool
NilOption*[T] = distinct T
CompositeOption*[T] = object
has: bool
val: T
Option*[T] = NilOption[T] or CompositeOption[T]
template `?`*(T: typedesc): typedesc =
when T is Nullable:
NilOption[T]
else:
CompositeOption[T]
proc some*[T](val: T): auto =
when T is Nullable:
assert(not isNil(val))
NilOption[T](val)
else:
CompositeOption[T](has: true, val: val)
proc none*(T: typedesc): auto =
when T is Nullable:
NilOption[T](nil)
else:
CompositeOption[T]()
proc has*[T](opt: Option[T]): bool =
when opt is NilOption:
not isNil(T(opt))
else:
opt.has
converter toBool*(opt: Option): bool =
opt.has
proc val*[T](opt: Option[T]): T =
when opt is NilOption:
T(opt)
else:
opt.val
proc get*[T](opt: Option[T]): T =
if not opt:
raise newException(FieldError, "Cannot fetch value from a None")
opt.val
proc get*[T](opt: Option[T], default: T): T =
if opt:
opt.val
else:
default
template `?=`(into: expr, opt: Option): bool =
var into {.inject.}: type(opt.val)
if opt:
into = opt.val
opt
var s: ?string
assert s is NilOption[string]
s = some "asd"
if s:
echo s.get
#< asd
s = none string
if s:
echo s.val
var x: ?int
assert x is CompositeOption[int]
x = some 5
if x:
echo x.get
#< 5
x = none int
if s:
echo x.val
proc test(): ?string =
some "abc"
if r ?= test():
echo r
#< abc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment