Spec-Zone.ru › Nim

std/wrapnils

Source Edit

Этот модуль позволяет безопасно вычислять выражения при следующих условиях:

  • обращение к nil
  • доступ к полям с неправильным дискриминантом в объектах case

default(T) возвращается в тех случаях, когда вычисляется выражение типа T. Это упрощает код, уменьшая необходимость использования ветвлений if-else.

Примечание: экспериментальный модуль, неустойчивый API.

Пример:

import std/wrapnils
type Foo = ref object
  x1: string
  x2: Foo
  x3: ref int

var f: Foo
assert ?.f.x2.x1 == "" # returns default value since `f` is nil

var f2 = Foo(x1: "a")
f2.x2 = f2
assert ?.f2.x1 == "a" # same as f2.x1 (no nil LHS in this chain)
assert ?.Foo(x1: "a").x1 == "a" # can use constructor inside

# when you know a sub-expression doesn't involve a `nil` (e.g. `f2.x2.x2`),
# you can scope it as follows:
assert ?.(f2.x2.x2).x3[] == 0

assert (?.f2.x2.x2).x3 == nil  # this terminates ?. early

Пример:

import std/wrapnils
# ?. also allows case object
type B = object
  b0: int
  case cond: bool
  of false: discard
  of true:
    b1: float

var b = B(cond: false, b0: 3)
doAssertRaises(FieldDefect): discard b.b1 # wrong discriminant
doAssert ?.b.b1 == 0.0 # safe
b = B(cond: true, b1: 4.5)
doAssert ?.b.b1 == 4.5

# lvalue semantics are preserved:
if (let p = ?.b.b1.addr; p != nil): p[] = 4.7
doAssert b.b1 == 4.7

Импорты

macros, options

Процедуры

func `[]`[T, I](a: Option[T]; i: I): auto {.inline.}
См. пример выше. Source Edit
func `[]`[U](a: Option[U]): auto {.inline.}
См. пример выше. Source Edit

Макросы

macro `?.`(a: typed): auto
Преобразует a в выражение, которое можно безопасно вычислять даже при наличии промежуточных nil указателей/ссылок, в этом случае генерируется значение по умолчанию. Source Edit
macro `??.`(a: typed): Option
Аналогично ?., но возвращает Option.

Пример:

import std/options
type Foo = ref object
  x1: ref int
  x2: int
# `?.` can't distinguish between a valid vs invalid default value, but `??.` can:
var f1 = Foo(x1: int.new, x2: 2)
doAssert (??.f1.x1[]).get == 0 # not enough to tell when the chain was valid.
doAssert (??.f1.x1[]).isSome # a nil didn't occur in the chain
doAssert (??.f1.x2).get == 2

var f2: Foo
doAssert not (??.f2.x1[]).isSome # f2 was nil

doAssertRaises(UnpackDefect): discard (??.f2.x1[]).get
doAssert ?.f2.x1[] == 0 # in contrast, this returns default(int)
Source Edit

Шаблоны

template fakeDot(a: Option; b): untyped
См. пример выше. Source Edit

© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/wrapnils.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API