option optimization (#6253)
This commit is contained in:
parent
6baca58693
commit
e7edc7ec7f
1 changed files with 49 additions and 15 deletions
|
|
@ -69,26 +69,51 @@
|
||||||
## discard
|
## discard
|
||||||
import typetraits
|
import typetraits
|
||||||
|
|
||||||
|
type
|
||||||
|
SomePointer = ref | ptr | pointer
|
||||||
|
|
||||||
type
|
type
|
||||||
Option*[T] = object
|
Option*[T] = object
|
||||||
## An optional type that stores its value and state separately in a boolean.
|
## An optional type that stores its value and state separately in a boolean.
|
||||||
|
when T is SomePointer:
|
||||||
|
val: T
|
||||||
|
else:
|
||||||
val: T
|
val: T
|
||||||
has: bool
|
has: bool
|
||||||
|
|
||||||
UnpackError* = ref object of ValueError
|
UnpackError* = ref object of ValueError
|
||||||
|
|
||||||
proc some*[T](val: T): Option[T] =
|
proc some*[T](val: T): Option[T] =
|
||||||
## Returns a ``Option`` that has this value.
|
## Returns a ``Option`` that has this value.
|
||||||
|
when T is SomePointer:
|
||||||
|
assert val != nil
|
||||||
|
result.val = val
|
||||||
|
else:
|
||||||
result.has = true
|
result.has = true
|
||||||
result.val = val
|
result.val = val
|
||||||
|
|
||||||
proc none*(T: typedesc): Option[T] =
|
proc option*[T](val: T): Option[T] =
|
||||||
## Returns a ``Option`` for this type that has no value.
|
## Can be used to convert a pointer type to an option type. It
|
||||||
result.has = false
|
## converts ``nil`` to the none-option.
|
||||||
|
result.val = val
|
||||||
|
when T isnot SomePointer:
|
||||||
|
result.has = true
|
||||||
|
|
||||||
proc isSome*[T](self: Option[T]): bool =
|
proc none*(T: typedesc): Option[T] =
|
||||||
|
## Returns an ``Option`` for this type that has no value.
|
||||||
|
# the default is the none type
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc isSome*[T](self: Option[T]): bool {.inline.} =
|
||||||
|
when T is SomePointer:
|
||||||
|
self.val != nil
|
||||||
|
else:
|
||||||
self.has
|
self.has
|
||||||
|
|
||||||
proc isNone*[T](self: Option[T]): bool =
|
proc isNone*[T](self: Option[T]): bool {.inline.} =
|
||||||
|
when T is SomePointer:
|
||||||
|
self.val == nil
|
||||||
|
else:
|
||||||
not self.has
|
not self.has
|
||||||
|
|
||||||
proc unsafeGet*[T](self: Option[T]): T =
|
proc unsafeGet*[T](self: Option[T]): T =
|
||||||
|
|
@ -112,13 +137,13 @@ proc get*[T](self: Option[T], otherwise: T): T =
|
||||||
|
|
||||||
proc map*[T](self: Option[T], callback: proc (input: T)) =
|
proc map*[T](self: Option[T], callback: proc (input: T)) =
|
||||||
## Applies a callback to the value in this Option
|
## Applies a callback to the value in this Option
|
||||||
if self.has:
|
if self.isSome:
|
||||||
callback(self.val)
|
callback(self.val)
|
||||||
|
|
||||||
proc map*[T, R](self: Option[T], callback: proc (input: T): R): Option[R] =
|
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
|
## 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.
|
## containing the new value. If this option is None, None will be returned
|
||||||
if self.has:
|
if self.isSome:
|
||||||
some[R]( callback(self.val) )
|
some[R]( callback(self.val) )
|
||||||
else:
|
else:
|
||||||
none(R)
|
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
|
## 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
|
## `true`, the option is returned as a Some. If it returns false, it is
|
||||||
## returned as a None.
|
## returned as a None.
|
||||||
if self.has and not callback(self.val):
|
if self.isSome and not callback(self.val):
|
||||||
none(T)
|
none(T)
|
||||||
else:
|
else:
|
||||||
self
|
self
|
||||||
|
|
@ -256,3 +281,12 @@ when isMainModule:
|
||||||
|
|
||||||
check(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!"))
|
check(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!"))
|
||||||
check(some(0).flatMap(maybeToString).flatMap(maybeExclaim) == none(string))
|
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))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue