diff options
author | Arne Döring <arne.doering@gmx.net> | 2018-04-11 16:50:27 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-04-11 16:50:27 +0200 |
commit | e7edc7ec7f5990c80f0bb1ff9d1cd7f0b000bb0e (patch) | |
tree | 99acc56bcb8f4044e4a5cc78db03aef8f308dd3b /lib/pure | |
parent | 6baca58693672f8fc9485272b3c350d0b0b77163 (diff) | |
download | Nim-e7edc7ec7f5990c80f0bb1ff9d1cd7f0b000bb0e.tar.gz |
option optimization (#6253)
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/options.nim | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/lib/pure/options.nim b/lib/pure/options.nim index 6d2869bff..8a771be71 100644 --- a/lib/pure/options.nim +++ b/lib/pure/options.nim @@ -70,26 +70,51 @@ import typetraits type + SomePointer = ref | ptr | pointer + +type Option*[T] = object ## An optional type that stores its value and state separately in a boolean. - val: T - has: bool + when T is SomePointer: + val: T + else: + val: T + has: bool + UnpackError* = ref object of ValueError proc some*[T](val: T): Option[T] = ## Returns a ``Option`` that has this value. - result.has = true + when T is SomePointer: + assert val != nil + result.val = val + else: + result.has = true + result.val = val + +proc option*[T](val: T): Option[T] = + ## Can be used to convert a pointer type to an option type. It + ## converts ``nil`` to the none-option. result.val = val + when T isnot SomePointer: + result.has = true proc none*(T: typedesc): Option[T] = - ## Returns a ``Option`` for this type that has no value. - result.has = false + ## Returns an ``Option`` for this type that has no value. + # the default is the none type + discard -proc isSome*[T](self: Option[T]): bool = - self.has +proc isSome*[T](self: Option[T]): bool {.inline.} = + when T is SomePointer: + self.val != nil + else: + self.has -proc isNone*[T](self: Option[T]): bool = - not self.has +proc isNone*[T](self: Option[T]): bool {.inline.} = + when T is SomePointer: + self.val == nil + else: + not self.has proc unsafeGet*[T](self: Option[T]): T = ## Returns the value of a ``some``. Behavior is undefined for ``none``. @@ -112,14 +137,14 @@ proc get*[T](self: Option[T], otherwise: T): T = proc map*[T](self: Option[T], callback: proc (input: T)) = ## Applies a callback to the value in this Option - if self.has: + if self.isSome: callback(self.val) proc map*[T, R](self: Option[T], callback: proc (input: T): R): Option[R] = ## Applies a callback to the value in this Option and returns an option - ## containing the new value. If this option is None, None will be returned. - if self.has: - some[R](callback(self.val)) + ## containing the new value. If this option is None, None will be returned + if self.isSome: + some[R]( callback(self.val) ) else: none(R) @@ -142,7 +167,7 @@ proc filter*[T](self: Option[T], callback: proc (input: T): bool): Option[T] = ## Applies a callback to the value in this Option. If the callback returns ## `true`, the option is returned as a Some. If it returns false, it is ## returned as a None. - if self.has and not callback(self.val): + if self.isSome and not callback(self.val): none(T) else: self @@ -155,7 +180,7 @@ proc `==`*(a, b: Option): bool = proc `$`*[T](self: Option[T]): string = ## Get the string representation of this option. If the option has a value, ## the result will be `Some(x)` where `x` is the string representation of the contained value. - ## If the option does not have a value, the result will be `None[T]` where `T` is the name of + ## If the option does not have a value, the result will be `None[T]` where `T` is the name of ## the type contained in the option. if self.has: "Some(" & $self.val & ")" @@ -256,3 +281,12 @@ when isMainModule: check(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!")) check(some(0).flatMap(maybeToString).flatMap(maybeExclaim) == none(string)) + + test "SomePointer": + var intref: ref int + check(option(intref).isNone) + intref.new + check(option(intref).isSome) + + let tmp = option(intref) + check(sizeof(tmp) == sizeof(ptr int)) |