treturn_inference.nim 3.8 KB

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