1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
{.experimental: "inferGenericTypes".}
import std/tables
block:
type
MyOption[T, Z] = object
x: T
y: Z
proc none[T, Z](): MyOption[T, Z] =
when T is int:
result.x = 22
when Z is float:
result.y = 12.0
proc myGenericProc[T, Z](): MyOption[T, Z] =
none() # implied by return type
let a = myGenericProc[int, float]()
doAssert a.x == 22
doAssert a.y == 12.0
let b: MyOption[int, float] = none() # implied by type of b
doAssert b.x == 22
doAssert b.y == 12.0
# Simple template based result with inferred type for errors
block:
type
ResultKind {.pure.} = enum
Ok
Err
Result[T] = object
case kind: ResultKind
of Ok:
data: T
of Err:
errmsg: cstring
template err[T](msg: static cstring): Result[T] =
Result[T](kind : ResultKind.Err, errmsg : msg)
proc testproc(): Result[int] =
err("Inferred error!") # implied by proc return
let r = testproc()
doAssert r.kind == ResultKind.Err
doAssert r.errmsg == "Inferred error!"
# Builtin seq
block:
let x: seq[int] = newSeq(1)
doAssert x is seq[int]
doAssert x.len() == 1
type
MyType[T, Z] = object
x: T
y: Z
let y: seq[MyType[int, float]] = newSeq(2)
doAssert y is seq[MyType[int, float]]
doAssert y.len() == 2
let z = MyType[seq[float], string](
x : newSeq(3),
y : "test"
)
doAssert z.x is seq[float]
doAssert z.x.len() == 3
doAssert z.y is string
doAssert z.y == "test"
# array
block:
proc giveArray[N, T](): array[N, T] =
for i in 0 .. N.high:
result[i] = i
var x: array[2, int] = giveArray()
doAssert x == [0, 1]
# tuples
block:
proc giveTuple[T, Z]: (T, Z, T) = discard
let x: (int, float, int) = giveTuple()
doAssert x is (int, float, int)
doAssert x == (0, 0.0, 0)
proc giveNamedTuple[T, Z]: tuple[a: T, b: Z] = discard
let y: tuple[a: int, b: float] = giveNamedTuple()
doAssert y is (int, float)
doAssert y is tuple[a: int, b: float]
doAssert y == (0, 0.0)
proc giveNestedTuple[T, Z]: ((T, Z), Z) = discard
let z: ((int, float), float) = giveNestedTuple()
doAssert z is ((int, float), float)
doAssert z == ((0, 0.0), 0.0)
# nesting inside a generic type
type MyType[T] = object
x: T
let a = MyType[(int, MyType[float])](x : giveNamedTuple())
doAssert a.x is (int, MyType[float])
# basic constructors
block:
type MyType[T] = object
x: T
proc giveValue[T](): T =
when T is int:
12
else:
default(T)
let x = MyType[int](x : giveValue())
doAssert x.x is int
doAssert x.x == 12
let y = MyType[MyType[float]](x : MyType[float](x : giveValue()))
doAssert y.x is MyType[float]
doAssert y.x.x is float
doAssert y.x.x == 0.0
# 'MyType[float]' is bound to 'T' directly
# instead of mapping 'T' to 'float'
let z = MyType[MyType[float]](x : giveValue())
doAssert z.x is MyType[float]
doAssert z.x.x == 0.0
type Foo = object
x: Table[int, float]
let a = Foo(x: initTable())
doAssert a.x is Table[int, float]
# partial binding
block:
type
ResultKind = enum
Ok, Error
Result[T, E] = object
case kind: ResultKind
of Ok:
okVal: T
of Error:
errVal: E
proc err[T, E](myParam: E): Result[T, E] =
Result[T, E](kind : Error, errVal : myParam)
proc doStuff(): Result[int, string] =
err("Error")
let res = doStuff()
doAssert res.kind == Error
doAssert res.errVal == "Error"
# ufcs
block:
proc getValue[T](_: string): T =
doAssert T is int
44
proc `'test`[T](_: string): T =
55
let a: int = getValue("")
let b: int = "".getValue()
let c: int = "".getValue
let d: int = getValue ""
let e: int = getValue""
let f: int = 12345'test
doAssert a == 44
doAssert b == 44
doAssert c == 44
doAssert d == 44
doAssert e == 44
doAssert f == 55
|