iterators.nim 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. ## Default iterators for some Nim types.
  2. when defined(nimPreviewSlimSystem):
  3. import std/assertions
  4. when not defined(nimNoLentIterators):
  5. template lent2(T): untyped = lent T
  6. else:
  7. template lent2(T): untyped = T
  8. iterator items*[T: not char](a: openArray[T]): lent2 T {.inline.} =
  9. ## Iterates over each item of `a`.
  10. var i = 0
  11. while i < len(a):
  12. yield a[i]
  13. inc(i)
  14. iterator items*[T: char](a: openArray[T]): T {.inline.} =
  15. ## Iterates over each item of `a`.
  16. # a VM bug currently prevents taking address of openArray[char]
  17. # elements converted from a string (would fail in `tests/misc/thallo.nim`)
  18. # in any case there's no performance advantage of returning char by address.
  19. var i = 0
  20. while i < len(a):
  21. yield a[i]
  22. inc(i)
  23. iterator mitems*[T](a: var openArray[T]): var T {.inline.} =
  24. ## Iterates over each item of `a` so that you can modify the yielded value.
  25. var i = 0
  26. while i < len(a):
  27. yield a[i]
  28. inc(i)
  29. iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
  30. ## Iterates over each item of `a`.
  31. when a.len > 0:
  32. var i = low(IX)
  33. while true:
  34. yield a[i]
  35. if i >= high(IX): break
  36. inc(i)
  37. iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} =
  38. ## Iterates over each item of `a` so that you can modify the yielded value.
  39. when a.len > 0:
  40. var i = low(IX)
  41. while true:
  42. yield a[i]
  43. if i >= high(IX): break
  44. inc(i)
  45. iterator items*[T](a: set[T]): T {.inline.} =
  46. ## Iterates over each element of `a`. `items` iterates only over the
  47. ## elements that are really in the set (and not over the ones the set is
  48. ## able to hold).
  49. var i = low(T).int
  50. while i <= high(T).int:
  51. if T(i) in a: yield T(i)
  52. inc(i)
  53. iterator items*(a: cstring): char {.inline.} =
  54. ## Iterates over each item of `a`.
  55. runnableExamples:
  56. from std/sequtils import toSeq
  57. assert toSeq("abc\0def".cstring) == @['a', 'b', 'c']
  58. assert toSeq("abc".cstring) == @['a', 'b', 'c']
  59. #[
  60. assert toSeq(nil.cstring) == @[] # xxx fails with SIGSEGV
  61. this fails with SIGSEGV; unclear whether we want to instead yield nothing
  62. or pay a small price to check for `nil`, a benchmark is needed. Note that
  63. other procs support `nil`.
  64. ]#
  65. template impl() =
  66. var i = 0
  67. let n = len(a)
  68. while i < n:
  69. yield a[i]
  70. inc(i)
  71. when defined(js): impl()
  72. else:
  73. when nimvm:
  74. # xxx `cstring` should behave like c backend instead.
  75. impl()
  76. else:
  77. var i = 0
  78. while a[i] != '\0':
  79. yield a[i]
  80. inc(i)
  81. iterator mitems*(a: var cstring): var char {.inline.} =
  82. ## Iterates over each item of `a` so that you can modify the yielded value.
  83. # xxx this should give CT error in js RT.
  84. runnableExamples:
  85. from std/sugar import collect
  86. var a = "abc\0def"
  87. prepareMutation(a)
  88. var b = a.cstring
  89. let s = collect:
  90. for bi in mitems(b):
  91. if bi == 'b': bi = 'B'
  92. bi
  93. assert s == @['a', 'B', 'c']
  94. assert b == "aBc"
  95. assert a == "aBc\0def"
  96. template impl() =
  97. var i = 0
  98. let n = len(a)
  99. while i < n:
  100. yield a[i]
  101. inc(i)
  102. when defined(js): impl()
  103. else:
  104. when nimvm: impl()
  105. else:
  106. var i = 0
  107. while a[i] != '\0':
  108. yield a[i]
  109. inc(i)
  110. iterator items*[T: enum and Ordinal](E: typedesc[T]): T =
  111. ## Iterates over the values of `E`.
  112. ## See also `enumutils.items` for enums with holes.
  113. runnableExamples:
  114. type Goo = enum g0 = 2, g1, g2
  115. from std/sequtils import toSeq
  116. assert Goo.toSeq == [g0, g1, g2]
  117. for v in low(E) .. high(E):
  118. yield v
  119. iterator items*[T: Ordinal](s: Slice[T]): T =
  120. ## Iterates over the slice `s`, yielding each value between `s.a` and `s.b`
  121. ## (inclusively).
  122. for x in s.a .. s.b:
  123. yield x
  124. iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} =
  125. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  126. var i = 0
  127. while i < len(a):
  128. yield (i, a[i])
  129. inc(i)
  130. iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.} =
  131. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  132. ## `a[index]` can be modified.
  133. var i = 0
  134. while i < len(a):
  135. yield (i, a[i])
  136. inc(i)
  137. iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
  138. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  139. when a.len > 0:
  140. var i = low(IX)
  141. while true:
  142. yield (i, a[i])
  143. if i >= high(IX): break
  144. inc(i)
  145. iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inline.} =
  146. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  147. ## `a[index]` can be modified.
  148. when a.len > 0:
  149. var i = low(IX)
  150. while true:
  151. yield (i, a[i])
  152. if i >= high(IX): break
  153. inc(i)
  154. iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} =
  155. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  156. var i = 0
  157. let L = len(a)
  158. while i < L:
  159. yield (i, a[i])
  160. inc(i)
  161. assert(len(a) == L, "the length of the seq changed while iterating over it")
  162. iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} =
  163. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  164. ## `a[index]` can be modified.
  165. var i = 0
  166. let L = len(a)
  167. while i < L:
  168. yield (i, a[i])
  169. inc(i)
  170. assert(len(a) == L, "the length of the seq changed while iterating over it")
  171. iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} =
  172. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  173. var i = 0
  174. let L = len(a)
  175. while i < L:
  176. yield (i, a[i])
  177. inc(i)
  178. assert(len(a) == L, "the length of the string changed while iterating over it")
  179. iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} =
  180. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  181. ## `a[index]` can be modified.
  182. var i = 0
  183. let L = len(a)
  184. while i < L:
  185. yield (i, a[i])
  186. inc(i)
  187. assert(len(a) == L, "the length of the string changed while iterating over it")
  188. iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} =
  189. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  190. when defined(js):
  191. var i = 0
  192. var L = len(a)
  193. while i < L:
  194. yield (i, a[i])
  195. inc(i)
  196. else:
  197. var i = 0
  198. while a[i] != '\0':
  199. yield (i, a[i])
  200. inc(i)
  201. iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
  202. ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
  203. ## `a[index]` can be modified.
  204. when defined(js):
  205. var i = 0
  206. var L = len(a)
  207. while i < L:
  208. yield (i, a[i])
  209. inc(i)
  210. else:
  211. var i = 0
  212. while a[i] != '\0':
  213. yield (i, a[i])
  214. inc(i)
  215. iterator items*[T](a: seq[T]): lent2 T {.inline.} =
  216. ## Iterates over each item of `a`.
  217. var i = 0
  218. let L = len(a)
  219. while i < L:
  220. yield a[i]
  221. inc(i)
  222. assert(len(a) == L, "the length of the seq changed while iterating over it")
  223. iterator mitems*[T](a: var seq[T]): var T {.inline.} =
  224. ## Iterates over each item of `a` so that you can modify the yielded value.
  225. var i = 0
  226. let L = len(a)
  227. while i < L:
  228. yield a[i]
  229. inc(i)
  230. assert(len(a) == L, "the length of the seq changed while iterating over it")
  231. iterator items*(a: string): char {.inline.} =
  232. ## Iterates over each item of `a`.
  233. var i = 0
  234. let L = len(a)
  235. while i < L:
  236. yield a[i]
  237. inc(i)
  238. assert(len(a) == L, "the length of the string changed while iterating over it")
  239. iterator mitems*(a: var string): var char {.inline.} =
  240. ## Iterates over each item of `a` so that you can modify the yielded value.
  241. var i = 0
  242. let L = len(a)
  243. while i < L:
  244. yield a[i]
  245. inc(i)
  246. assert(len(a) == L, "the length of the string changed while iterating over it")
  247. iterator fields*[T: tuple|object](x: T): RootObj {.
  248. magic: "Fields", noSideEffect.} =
  249. ## Iterates over every field of `x`.
  250. ##
  251. ## .. warning:: This really transforms the 'for' and unrolls the loop.
  252. ## The current implementation also has a bug
  253. ## that affects symbol binding in the loop body.
  254. runnableExamples:
  255. var t = (1, "foo")
  256. for v in fields(t): v = default(typeof(v))
  257. doAssert t == (0, "")
  258. iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[key: string, val: RootObj] {.
  259. magic: "Fields", noSideEffect.} =
  260. ## Iterates over every field of `x` and `y`.
  261. ##
  262. ## .. warning:: This really transforms the 'for' and unrolls the loop.
  263. ## The current implementation also has a bug that affects symbol binding
  264. ## in the loop body.
  265. runnableExamples:
  266. var t1 = (1, "foo")
  267. var t2 = default(typeof(t1))
  268. for v1, v2 in fields(t1, t2): v2 = v1
  269. doAssert t1 == t2
  270. iterator fieldPairs*[T: tuple|object](x: T): tuple[key: string, val: RootObj] {.
  271. magic: "FieldPairs", noSideEffect.} =
  272. ## Iterates over every field of `x` returning their name and value.
  273. ##
  274. ## When you iterate over objects with different field types you have to use
  275. ## the compile time `when` instead of a runtime `if` to select the code
  276. ## you want to run for each type. To perform the comparison use the `is
  277. ## operator <manual.html#generics-is-operator>`_.
  278. ## Another way to do the same without `when` is to leave the task of
  279. ## picking the appropriate code to a secondary proc which you overload for
  280. ## each field type and pass the `value` to.
  281. ##
  282. ## .. warning:: This really transforms the 'for' and unrolls the loop. The
  283. ## current implementation also has a bug that affects symbol binding in the
  284. ## loop body.
  285. runnableExamples:
  286. type
  287. Custom = object
  288. foo: string
  289. bar: bool
  290. proc `$`(x: Custom): string =
  291. result = "Custom:"
  292. for name, value in x.fieldPairs:
  293. when value is bool:
  294. result.add("\n\t" & name & " is " & $value)
  295. else:
  296. result.add("\n\t" & name & " '" & value & "'")
  297. iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[
  298. key: string, a, b: RootObj] {.
  299. magic: "FieldPairs", noSideEffect.} =
  300. ## Iterates over every field of `x` and `y`.
  301. ##
  302. ## .. warning:: This really transforms the 'for' and unrolls the loop.
  303. ## The current implementation also has a bug that affects symbol binding
  304. ## in the loop body.
  305. runnableExamples:
  306. type Foo = object
  307. x1: int
  308. x2: string
  309. var a1 = Foo(x1: 12, x2: "abc")
  310. var a2: Foo
  311. for name, v1, v2 in fieldPairs(a1, a2):
  312. when name == "x2": v2 = v1
  313. doAssert a2 == Foo(x1: 0, x2: "abc")