sequtils.nim 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2011 Alexander Mitchell-Robinson
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## :Author: Alexander Mitchell-Robinson (Amrykid)
  10. ##
  11. ## This module implements operations for the built-in `seq`:idx: type which
  12. ## were inspired by functional programming languages.
  13. ##
  14. ## For functional style programming you may want to pass `anonymous procs
  15. ## <manual.html#procedures-anonymous-procs>`_ to procs like ``filter`` to
  16. ## reduce typing. Anonymous procs can use `the special do notation
  17. ## <manual.html#procedures-do-notation>`_
  18. ## which is more convenient in certain situations.
  19. include "system/inclrtl"
  20. import macros
  21. when not defined(nimhygiene):
  22. {.pragma: dirty.}
  23. macro evalOnceAs(expAlias, exp: untyped, letAssigneable: static[bool]): untyped =
  24. ## Injects ``expAlias`` in caller scope, to avoid bugs involving multiple
  25. ## substitution in macro arguments such as
  26. ## https://github.com/nim-lang/Nim/issues/7187
  27. ## ``evalOnceAs(myAlias, myExp)`` will behave as ``let myAlias = myExp``
  28. ## except when ``letAssigneable`` is false (eg to handle openArray) where
  29. ## it just forwards ``exp`` unchanged
  30. expectKind(expAlias, nnkIdent)
  31. var val = exp
  32. result = newStmtList()
  33. # If `exp` is not a symbol we evaluate it once here and then use the temporary
  34. # symbol as alias
  35. if exp.kind != nnkSym and letAssigneable:
  36. val = genSym()
  37. result.add(newLetStmt(val, exp))
  38. result.add(
  39. newProc(name = genSym(nskTemplate, $expAlias), params = [getType(untyped)],
  40. body = val, procType = nnkTemplateDef))
  41. proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
  42. ## Takes several sequences' items and returns them inside a new sequence.
  43. ##
  44. ## Example:
  45. ##
  46. ## .. code-block::
  47. ## let
  48. ## s1 = @[1, 2, 3]
  49. ## s2 = @[4, 5]
  50. ## s3 = @[6, 7]
  51. ## total = concat(s1, s2, s3)
  52. ## assert total == @[1, 2, 3, 4, 5, 6, 7]
  53. var L = 0
  54. for seqitm in items(seqs): inc(L, len(seqitm))
  55. newSeq(result, L)
  56. var i = 0
  57. for s in items(seqs):
  58. for itm in items(s):
  59. result[i] = itm
  60. inc(i)
  61. proc count*[T](s: openArray[T], x: T): int =
  62. ## Returns the number of occurrences of the item `x` in the container `s`.
  63. ##
  64. ## Example:
  65. ##
  66. ## .. code-block::
  67. ## let
  68. ## s = @[1, 2, 2, 3, 2, 4, 2]
  69. ## c = count(s, 2)
  70. ## assert c == 4
  71. for itm in items(s):
  72. if itm == x:
  73. inc result
  74. proc cycle*[T](s: openArray[T], n: Natural): seq[T] =
  75. ## Returns a new sequence with the items of the container `s` repeated
  76. ## `n` times.
  77. ##
  78. ## Example:
  79. ##
  80. ## .. code-block::
  81. ##
  82. ## let
  83. ## s = @[1, 2, 3]
  84. ## total = s.cycle(3)
  85. ## assert total == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
  86. result = newSeq[T](n * s.len)
  87. var o = 0
  88. for x in 0 ..< n:
  89. for e in s:
  90. result[o] = e
  91. inc o
  92. proc repeat*[T](x: T, n: Natural): seq[T] =
  93. ## Returns a new sequence with the item `x` repeated `n` times.
  94. ##
  95. ## Example:
  96. ##
  97. ## .. code-block::
  98. ##
  99. ## let
  100. ## total = repeat(5, 3)
  101. ## assert total == @[5, 5, 5]
  102. result = newSeq[T](n)
  103. for i in 0 ..< n:
  104. result[i] = x
  105. proc deduplicate*[T](s: openArray[T], isSorted: bool = false): seq[T] =
  106. ## Returns a new sequence without duplicates.
  107. ##
  108. ## Example:
  109. ##
  110. ## .. code-block::
  111. ## let
  112. ## dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
  113. ## dup2 = @["a", "a", "c", "d", "d"]
  114. ## unique1 = deduplicate(dup1)
  115. ## unique2 = deduplicate(dup2)
  116. ## assert unique1 == @[1, 3, 4, 2, 8]
  117. ## assert unique2 == @["a", "c", "d"]
  118. result = @[]
  119. if s.len > 0:
  120. if isSorted:
  121. var prev = s[0]
  122. result.add(prev)
  123. for i in 1..s.high:
  124. if s[i] != prev:
  125. prev = s[i]
  126. result.add(prev)
  127. else:
  128. for itm in items(s):
  129. if not result.contains(itm): result.add(itm)
  130. proc zip*[S, T](s1: openArray[S], s2: openArray[T]): seq[tuple[a: S, b: T]] =
  131. ## Returns a new sequence with a combination of the two input containers.
  132. ##
  133. ## For convenience you can access the returned tuples through the named
  134. ## fields `a` and `b`. If one container is shorter, the remaining items in
  135. ## the longer container are discarded.
  136. ##
  137. ## Example:
  138. ##
  139. ## .. code-block::
  140. ## let
  141. ## short = @[1, 2, 3]
  142. ## long = @[6, 5, 4, 3, 2, 1]
  143. ## words = @["one", "two", "three"]
  144. ## zip1 = zip(short, long)
  145. ## zip2 = zip(short, words)
  146. ## assert zip1 == @[(1, 6), (2, 5), (3, 4)]
  147. ## assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
  148. ## assert zip1[2].b == 4
  149. ## assert zip2[2].b == "three"
  150. var m = min(s1.len, s2.len)
  151. newSeq(result, m)
  152. for i in 0 ..< m:
  153. result[i] = (s1[i], s2[i])
  154. proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
  155. ## Splits and distributes a sequence `s` into `num` sub sequences.
  156. ##
  157. ## Returns a sequence of `num` sequences. For some input values this is the
  158. ## inverse of the `concat <#concat>`_ proc. The proc will assert in debug
  159. ## builds if `s` is nil or `num` is less than one, and will likely crash on
  160. ## release builds. The input sequence `s` can be empty, which will produce
  161. ## `num` empty sequences.
  162. ##
  163. ## If `spread` is false and the length of `s` is not a multiple of `num`, the
  164. ## proc will max out the first sub sequences with ``1 + len(s) div num``
  165. ## entries, leaving the remainder of elements to the last sequence.
  166. ##
  167. ## On the other hand, if `spread` is true, the proc will distribute evenly
  168. ## the remainder of the division across all sequences, which makes the result
  169. ## more suited to multithreading where you are passing equal sized work units
  170. ## to a thread pool and want to maximize core usage.
  171. ##
  172. ## Example:
  173. ##
  174. ## .. code-block::
  175. ## let numbers = @[1, 2, 3, 4, 5, 6, 7]
  176. ## assert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
  177. ## assert numbers.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
  178. ## assert numbers.distribute(6)[0] == @[1, 2]
  179. ## assert numbers.distribute(6)[5] == @[7]
  180. if num < 2:
  181. result = @[s]
  182. return
  183. let num = int(num) # XXX probably only needed because of .. bug
  184. # Create the result and calculate the stride size and the remainder if any.
  185. result = newSeq[seq[T]](num)
  186. var
  187. stride = s.len div num
  188. first = 0
  189. last = 0
  190. extra = s.len mod num
  191. if extra == 0 or spread == false:
  192. # Use an algorithm which overcounts the stride and minimizes reading limits.
  193. if extra > 0: inc(stride)
  194. for i in 0 ..< num:
  195. result[i] = newSeq[T]()
  196. for g in first ..< min(s.len, first + stride):
  197. result[i].add(s[g])
  198. first += stride
  199. else:
  200. # Use an undercounting algorithm which *adds* the remainder each iteration.
  201. for i in 0 ..< num:
  202. last = first + stride
  203. if extra > 0:
  204. extra -= 1
  205. inc(last)
  206. result[i] = newSeq[T]()
  207. for g in first ..< last:
  208. result[i].add(s[g])
  209. first = last
  210. proc map*[T, S](s: openArray[T], op: proc (x: T): S {.closure.}):
  211. seq[S]{.inline.} =
  212. ## Returns a new sequence with the results of `op` applied to every item in
  213. ## the container `s`.
  214. ##
  215. ## Since the input is not modified you can use this version of ``map`` to
  216. ## transform the type of the elements in the input container.
  217. ##
  218. ## Example:
  219. ##
  220. ## .. code-block:: nim
  221. ## let
  222. ## a = @[1, 2, 3, 4]
  223. ## b = map(a, proc(x: int): string = $x)
  224. ## assert b == @["1", "2", "3", "4"]
  225. newSeq(result, s.len)
  226. for i in 0 ..< s.len:
  227. result[i] = op(s[i])
  228. proc map*[T](s: var openArray[T], op: proc (x: var T) {.closure.})
  229. {.deprecated.} =
  230. ## Applies `op` to every item in `s` modifying it directly.
  231. ##
  232. ## Note that this version of ``map`` requires your input and output types to
  233. ## be the same, since they are modified in-place.
  234. ##
  235. ## Example:
  236. ##
  237. ## .. code-block:: nim
  238. ## var a = @["1", "2", "3", "4"]
  239. ## echo repr(a)
  240. ## # --> ["1", "2", "3", "4"]
  241. ## map(a, proc(x: var string) = x &= "42")
  242. ## echo repr(a)
  243. ## # --> ["142", "242", "342", "442"]
  244. ## **Deprecated since version 0.12.0:** Use the ``apply`` proc instead.
  245. for i in 0 ..< s.len: op(s[i])
  246. proc apply*[T](s: var openArray[T], op: proc (x: var T) {.closure.})
  247. {.inline.} =
  248. ## Applies `op` to every item in `s` modifying it directly.
  249. ##
  250. ## Note that this requires your input and output types to
  251. ## be the same, since they are modified in-place.
  252. ## The parameter function takes a ``var T`` type parameter.
  253. ##
  254. ## Example:
  255. ##
  256. ## .. code-block:: nim
  257. ## var a = @["1", "2", "3", "4"]
  258. ## echo repr(a)
  259. ## # --> ["1", "2", "3", "4"]
  260. ## apply(a, proc(x: var string) = x &= "42")
  261. ## echo repr(a)
  262. ## # --> ["142", "242", "342", "442"]
  263. ##
  264. for i in 0 ..< s.len: op(s[i])
  265. proc apply*[T](s: var openArray[T], op: proc (x: T): T {.closure.})
  266. {.inline.} =
  267. ## Applies `op` to every item in `s` modifying it directly.
  268. ##
  269. ## Note that this requires your input and output types to
  270. ## be the same, since they are modified in-place.
  271. ## The parameter function takes and returns a ``T`` type variable.
  272. ##
  273. ## Example:
  274. ##
  275. ## .. code-block:: nim
  276. ## var a = @["1", "2", "3", "4"]
  277. ## echo repr(a)
  278. ## # --> ["1", "2", "3", "4"]
  279. ## apply(a, proc(x: string): string = x & "42")
  280. ## echo repr(a)
  281. ## # --> ["142", "242", "342", "442"]
  282. ##
  283. for i in 0 ..< s.len: s[i] = op(s[i])
  284. iterator filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): T =
  285. ## Iterates through a container and yields every item that fulfills the
  286. ## predicate.
  287. ##
  288. ## Example:
  289. ##
  290. ## .. code-block::
  291. ## let numbers = @[1, 4, 5, 8, 9, 7, 4]
  292. ## for n in filter(numbers, proc (x: int): bool = x mod 2 == 0):
  293. ## echo($n)
  294. ## # echoes 4, 8, 4 in separate lines
  295. for i in 0 ..< s.len:
  296. if pred(s[i]):
  297. yield s[i]
  298. proc filter*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): seq[T]
  299. {.inline.} =
  300. ## Returns a new sequence with all the items that fulfilled the predicate.
  301. ##
  302. ## Example:
  303. ##
  304. ## .. code-block::
  305. ## let
  306. ## colors = @["red", "yellow", "black"]
  307. ## f1 = filter(colors, proc(x: string): bool = x.len < 6)
  308. ## f2 = filter(colors) do (x: string) -> bool : x.len > 5
  309. ## assert f1 == @["red", "black"]
  310. ## assert f2 == @["yellow"]
  311. result = newSeq[T]()
  312. for i in 0 ..< s.len:
  313. if pred(s[i]):
  314. result.add(s[i])
  315. proc keepIf*[T](s: var seq[T], pred: proc(x: T): bool {.closure.})
  316. {.inline.} =
  317. ## Keeps the items in the passed sequence if they fulfilled the predicate.
  318. ## Same as the ``filter`` proc, but modifies the sequence directly.
  319. ##
  320. ## Example:
  321. ##
  322. ## .. code-block::
  323. ## var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1]
  324. ## keepIf(floats, proc(x: float): bool = x > 10)
  325. ## assert floats == @[13.0, 12.5, 10.1]
  326. var pos = 0
  327. for i in 0 ..< len(s):
  328. if pred(s[i]):
  329. if pos != i:
  330. shallowCopy(s[pos], s[i])
  331. inc(pos)
  332. setLen(s, pos)
  333. proc delete*[T](s: var seq[T]; first, last: Natural) =
  334. ## Deletes in `s` the items at position `first` .. `last`. This modifies
  335. ## `s` itself, it does not return a copy.
  336. ##
  337. ## Example:
  338. ##
  339. ##.. code-block::
  340. ## let outcome = @[1,1,1,1,1,1,1,1]
  341. ## var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
  342. ## dest.delete(3, 8)
  343. ## assert outcome == dest
  344. var i = first
  345. var j = last+1
  346. var newLen = len(s)-j+i
  347. while i < newLen:
  348. s[i].shallowCopy(s[j])
  349. inc(i)
  350. inc(j)
  351. setLen(s, newLen)
  352. proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) =
  353. ## Inserts items from `src` into `dest` at position `pos`. This modifies
  354. ## `dest` itself, it does not return a copy.
  355. ##
  356. ## Example:
  357. ##
  358. ##.. code-block::
  359. ## var dest = @[1,1,1,1,1,1,1,1]
  360. ## let
  361. ## src = @[2,2,2,2,2,2]
  362. ## outcome = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
  363. ## dest.insert(src, 3)
  364. ## assert dest == outcome
  365. var j = len(dest) - 1
  366. var i = len(dest) + len(src) - 1
  367. dest.setLen(i + 1)
  368. # Move items after `pos` to the end of the sequence.
  369. while j >= pos:
  370. dest[i].shallowCopy(dest[j])
  371. dec(i)
  372. dec(j)
  373. # Insert items from `dest` into `dest` at `pos`
  374. inc(j)
  375. for item in src:
  376. dest[j] = item
  377. inc(j)
  378. template filterIt*(s, pred: untyped): untyped =
  379. ## Returns a new sequence with all the items that fulfilled the predicate.
  380. ##
  381. ## Unlike the `proc` version, the predicate needs to be an expression using
  382. ## the ``it`` variable for testing, like: ``filterIt("abcxyz", it == 'x')``.
  383. ##
  384. ## Example:
  385. ##
  386. ## .. code-block::
  387. ## let
  388. ## temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44]
  389. ## acceptable = filterIt(temperatures, it < 50 and it > -10)
  390. ## notAcceptable = filterIt(temperatures, it > 50 or it < -10)
  391. ## assert acceptable == @[-2.0, 24.5, 44.31]
  392. ## assert notAcceptable == @[-272.15, 99.9, -113.44]
  393. var result = newSeq[type(s[0])]()
  394. for it {.inject.} in items(s):
  395. if pred: result.add(it)
  396. result
  397. template keepItIf*(varSeq: seq, pred: untyped) =
  398. ## Convenience template around the ``keepIf`` proc to reduce typing.
  399. ##
  400. ## Unlike the `proc` version, the predicate needs to be an expression using
  401. ## the ``it`` variable for testing, like: ``keepItIf("abcxyz", it == 'x')``.
  402. ##
  403. ## Example:
  404. ##
  405. ## .. code-block::
  406. ## var candidates = @["foo", "bar", "baz", "foobar"]
  407. ## keepItIf(candidates, it.len == 3 and it[0] == 'b')
  408. ## assert candidates == @["bar", "baz"]
  409. var pos = 0
  410. for i in 0 ..< len(varSeq):
  411. let it {.inject.} = varSeq[i]
  412. if pred:
  413. if pos != i:
  414. shallowCopy(varSeq[pos], varSeq[i])
  415. inc(pos)
  416. setLen(varSeq, pos)
  417. proc all*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool =
  418. ## Iterates through a container and checks if every item fulfills the
  419. ## predicate.
  420. ##
  421. ## Example:
  422. ##
  423. ## .. code-block::
  424. ## let numbers = @[1, 4, 5, 8, 9, 7, 4]
  425. ## assert all(numbers, proc (x: int): bool = return x < 10) == true
  426. ## assert all(numbers, proc (x: int): bool = return x < 9) == false
  427. for i in s:
  428. if not pred(i):
  429. return false
  430. return true
  431. template allIt*(s, pred: untyped): bool =
  432. ## Checks if every item fulfills the predicate.
  433. ##
  434. ## Example:
  435. ##
  436. ## .. code-block::
  437. ## let numbers = @[1, 4, 5, 8, 9, 7, 4]
  438. ## assert allIt(numbers, it < 10) == true
  439. ## assert allIt(numbers, it < 9) == false
  440. var result = true
  441. for it {.inject.} in items(s):
  442. if not pred:
  443. result = false
  444. break
  445. result
  446. proc any*[T](s: openArray[T], pred: proc(x: T): bool {.closure.}): bool =
  447. ## Iterates through a container and checks if some item fulfills the
  448. ## predicate.
  449. ##
  450. ## Example:
  451. ##
  452. ## .. code-block::
  453. ## let numbers = @[1, 4, 5, 8, 9, 7, 4]
  454. ## assert any(numbers, proc (x: int): bool = return x > 8) == true
  455. ## assert any(numbers, proc (x: int): bool = return x > 9) == false
  456. for i in s:
  457. if pred(i):
  458. return true
  459. return false
  460. template anyIt*(s, pred: untyped): bool =
  461. ## Checks if some item fulfills the predicate.
  462. ##
  463. ## Example:
  464. ##
  465. ## .. code-block::
  466. ## let numbers = @[1, 4, 5, 8, 9, 7, 4]
  467. ## assert anyIt(numbers, it > 8) == true
  468. ## assert anyIt(numbers, it > 9) == false
  469. var result = false
  470. for it {.inject.} in items(s):
  471. if pred:
  472. result = true
  473. break
  474. result
  475. template toSeq1(s: not iterator): untyped =
  476. # overload for typed but not iterator
  477. type outType = type(items(s))
  478. when compiles(s.len):
  479. block:
  480. evalOnceAs(s2, s, compiles((let _ = s)))
  481. var i = 0
  482. var result = newSeq[outType](s2.len)
  483. for it in s2:
  484. result[i] = it
  485. i += 1
  486. result
  487. else:
  488. var result: seq[outType] = @[]
  489. for it in s:
  490. result.add(it)
  491. result
  492. template toSeq2(iter: iterator): untyped =
  493. # overload for iterator
  494. evalOnceAs(iter2, iter(), false)
  495. when compiles(iter2.len):
  496. var i = 0
  497. var result = newSeq[type(iter2)](iter2.len)
  498. for x in iter2:
  499. result[i] = x
  500. inc i
  501. result
  502. else:
  503. type outType = type(iter2())
  504. var result: seq[outType] = @[]
  505. when compiles(iter2()):
  506. evalOnceAs(iter4, iter, false)
  507. let iter3=iter4()
  508. for x in iter3():
  509. result.add(x)
  510. else:
  511. for x in iter2():
  512. result.add(x)
  513. result
  514. template toSeq*(iter: untyped): untyped =
  515. ## Transforms any iterable into a sequence.
  516. runnableExamples:
  517. let
  518. numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
  519. odd_numbers = toSeq(filter(numeric, proc(x: int): bool = x mod 2 == 1))
  520. doAssert odd_numbers == @[1, 3, 5, 7, 9]
  521. when compiles(toSeq1(iter)):
  522. toSeq1(iter)
  523. elif compiles(toSeq2(iter)):
  524. toSeq2(iter)
  525. else:
  526. # overload for untyped, eg: `toSeq(myInlineIterator(3))`
  527. when compiles(iter.len):
  528. block:
  529. evalOnceAs(iter2, iter, true)
  530. var result = newSeq[type(iter)](iter2.len)
  531. var i = 0
  532. for x in iter2:
  533. result[i] = x
  534. inc i
  535. result
  536. else:
  537. var result: seq[type(iter)] = @[]
  538. for x in iter:
  539. result.add(x)
  540. result
  541. template foldl*(sequence, operation: untyped): untyped =
  542. ## Template to fold a sequence from left to right, returning the accumulation.
  543. ##
  544. ## The sequence is required to have at least a single element. Debug versions
  545. ## of your program will assert in this situation but release versions will
  546. ## happily go ahead. If the sequence has a single element it will be returned
  547. ## without applying ``operation``.
  548. ##
  549. ## The ``operation`` parameter should be an expression which uses the
  550. ## variables ``a`` and ``b`` for each step of the fold. Since this is a left
  551. ## fold, for non associative binary operations like subtraction think that
  552. ## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) -
  553. ## 3).
  554. ##
  555. ## Example:
  556. ##
  557. ## .. code-block::
  558. ## let
  559. ## numbers = @[5, 9, 11]
  560. ## addition = foldl(numbers, a + b)
  561. ## subtraction = foldl(numbers, a - b)
  562. ## multiplication = foldl(numbers, a * b)
  563. ## words = @["nim", "is", "cool"]
  564. ## concatenation = foldl(words, a & b)
  565. ## assert addition == 25, "Addition is (((5)+9)+11)"
  566. ## assert subtraction == -15, "Subtraction is (((5)-9)-11)"
  567. ## assert multiplication == 495, "Multiplication is (((5)*9)*11)"
  568. ## assert concatenation == "nimiscool"
  569. let s = sequence
  570. assert s.len > 0, "Can't fold empty sequences"
  571. var result: type(s[0])
  572. result = s[0]
  573. for i in 1..<s.len:
  574. let
  575. a {.inject.} = result
  576. b {.inject.} = s[i]
  577. result = operation
  578. result
  579. template foldl*(sequence, operation, first): untyped =
  580. ## Template to fold a sequence from left to right, returning the accumulation.
  581. ##
  582. ## This version of ``foldl`` gets a starting parameter. This makes it possible
  583. ## to accumulate the sequence into a different type than the sequence elements.
  584. ##
  585. ## The ``operation`` parameter should be an expression which uses the variables
  586. ## ``a`` and ``b`` for each step of the fold. The ``first`` parameter is the
  587. ## start value (the first ``a``) and therefor defines the type of the result.
  588. ##
  589. ## Example:
  590. ##
  591. ## .. code-block::
  592. ## let
  593. ## numbers = @[0, 8, 1, 5]
  594. ## digits = foldl(numbers, a & (chr(b + ord('0'))), "")
  595. ## assert digits == "0815"
  596. var result: type(first)
  597. result = first
  598. for x in items(sequence):
  599. let
  600. a {.inject.} = result
  601. b {.inject.} = x
  602. result = operation
  603. result
  604. template foldr*(sequence, operation: untyped): untyped =
  605. ## Template to fold a sequence from right to left, returning the accumulation.
  606. ##
  607. ## The sequence is required to have at least a single element. Debug versions
  608. ## of your program will assert in this situation but release versions will
  609. ## happily go ahead. If the sequence has a single element it will be returned
  610. ## without applying ``operation``.
  611. ##
  612. ## The ``operation`` parameter should be an expression which uses the
  613. ## variables ``a`` and ``b`` for each step of the fold. Since this is a right
  614. ## fold, for non associative binary operations like subtraction think that
  615. ## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 -
  616. ## (3))).
  617. ##
  618. ## Example:
  619. ##
  620. ## .. code-block::
  621. ## let
  622. ## numbers = @[5, 9, 11]
  623. ## addition = foldr(numbers, a + b)
  624. ## subtraction = foldr(numbers, a - b)
  625. ## multiplication = foldr(numbers, a * b)
  626. ## words = @["nim", "is", "cool"]
  627. ## concatenation = foldr(words, a & b)
  628. ## assert addition == 25, "Addition is (5+(9+(11)))"
  629. ## assert subtraction == 7, "Subtraction is (5-(9-(11)))"
  630. ## assert multiplication == 495, "Multiplication is (5*(9*(11)))"
  631. ## assert concatenation == "nimiscool"
  632. let s = sequence
  633. assert s.len > 0, "Can't fold empty sequences"
  634. var result: type(s[0])
  635. result = sequence[s.len - 1]
  636. for i in countdown(s.len - 2, 0):
  637. let
  638. a {.inject.} = s[i]
  639. b {.inject.} = result
  640. result = operation
  641. result
  642. template mapIt*(s, typ, op: untyped): untyped =
  643. ## Convenience template around the ``map`` proc to reduce typing.
  644. ##
  645. ## The template injects the ``it`` variable which you can use directly in an
  646. ## expression. You also need to pass as `typ` the type of the expression,
  647. ## since the new returned sequence can have a different type than the
  648. ## original.
  649. ##
  650. ## Example:
  651. ##
  652. ## .. code-block::
  653. ## let
  654. ## nums = @[1, 2, 3, 4]
  655. ## strings = nums.mapIt(string, $(4 * it))
  656. ## assert strings == @["4", "8", "12", "16"]
  657. ## **Deprecated since version 0.12.0:** Use the ``mapIt(seq1, op)``
  658. ## template instead.
  659. var result: seq[typ] = @[]
  660. for it {.inject.} in items(s):
  661. result.add(op)
  662. result
  663. template mapIt*(s: typed, op: untyped): untyped =
  664. ## Convenience template around the ``map`` proc to reduce typing.
  665. ##
  666. ## The template injects the ``it`` variable which you can use directly in an
  667. ## expression.
  668. ##
  669. ## Example:
  670. ##
  671. ## .. code-block::
  672. ## let
  673. ## nums = @[1, 2, 3, 4]
  674. ## strings = nums.mapIt($(4 * it))
  675. ## assert strings == @["4", "8", "12", "16"]
  676. when defined(nimHasTypeof):
  677. type outType = typeof((
  678. block:
  679. var it{.inject.}: typeof(items(s), typeOfIter);
  680. op), typeOfProc)
  681. else:
  682. type outType = type((
  683. block:
  684. var it{.inject.}: type(items(s));
  685. op))
  686. when compiles(s.len):
  687. block: # using a block avoids https://github.com/nim-lang/Nim/issues/8580
  688. # BUG: `evalOnceAs(s2, s, false)` would lead to C compile errors
  689. # (`error: use of undeclared identifier`) instead of Nim compile errors
  690. evalOnceAs(s2, s, compiles((let _ = s)))
  691. var i = 0
  692. var result = newSeq[outType](s2.len)
  693. for it {.inject.} in s2:
  694. result[i] = op
  695. i += 1
  696. result
  697. else:
  698. var result: seq[outType] = @[]
  699. for it {.inject.} in s:
  700. result.add(op)
  701. result
  702. template applyIt*(varSeq, op: untyped) =
  703. ## Convenience template around the mutable ``apply`` proc to reduce typing.
  704. ##
  705. ## The template injects the ``it`` variable which you can use directly in an
  706. ## expression. The expression has to return the same type as the sequence you
  707. ## are mutating.
  708. ##
  709. ## Example:
  710. ##
  711. ## .. code-block::
  712. ## var nums = @[1, 2, 3, 4]
  713. ## nums.applyIt(it * 3)
  714. ## assert nums[0] + nums[3] == 15
  715. for i in low(varSeq) .. high(varSeq):
  716. let it {.inject.} = varSeq[i]
  717. varSeq[i] = op
  718. template newSeqWith*(len: int, init: untyped): untyped =
  719. ## creates a new sequence, calling `init` to initialize each value.
  720. ##
  721. ## Example:
  722. ##
  723. ## .. code-block::
  724. ## var seq2D = newSeqWith(20, newSeq[bool](10))
  725. ## seq2D[0][0] = true
  726. ## seq2D[1][0] = true
  727. ## seq2D[0][1] = true
  728. ##
  729. ## import random
  730. ## var seqRand = newSeqWith(20, random(10))
  731. ## echo seqRand
  732. var result = newSeq[type(init)](len)
  733. for i in 0 ..< len:
  734. result[i] = init
  735. result
  736. proc mapLitsImpl(constructor: NimNode; op: NimNode; nested: bool;
  737. filter = nnkLiterals): NimNode =
  738. if constructor.kind in filter:
  739. result = newNimNode(nnkCall, lineInfoFrom=constructor)
  740. result.add op
  741. result.add constructor
  742. else:
  743. result = copyNimNode(constructor)
  744. for v in constructor:
  745. if nested or v.kind in filter:
  746. result.add mapLitsImpl(v, op, nested, filter)
  747. else:
  748. result.add v
  749. macro mapLiterals*(constructor, op: untyped;
  750. nested = true): untyped =
  751. ## applies ``op`` to each of the **atomic** literals like ``3``
  752. ## or ``"abc"`` in the specified ``constructor`` AST. This can
  753. ## be used to map every array element to some target type:
  754. ##
  755. ## Example:
  756. ##
  757. ## .. code-block::
  758. ## let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
  759. ## doAssert x is array[4, int]
  760. ##
  761. ## Short notation for:
  762. ##
  763. ## .. code-block::
  764. ## let x = [int(0.1), int(1.2), int(2.3), int(3.4)]
  765. ##
  766. ## If ``nested`` is true, the literals are replaced everywhere
  767. ## in the ``constructor`` AST, otherwise only the first level
  768. ## is considered:
  769. ##
  770. ## .. code-block::
  771. ## mapLiterals((1, ("abc"), 2), float, nested=false)
  772. ##
  773. ## Produces::
  774. ##
  775. ## (float(1), ("abc"), float(2))
  776. ##
  777. ## There are no constraints for the ``constructor`` AST, it
  778. ## works for nested tuples of arrays of sets etc.
  779. result = mapLitsImpl(constructor, op, nested.boolVal)
  780. when isMainModule:
  781. import strutils
  782. from algorithm import sorted
  783. # helper for testing double substitution side effects which are handled
  784. # by `evalOnceAs`
  785. var counter = 0
  786. proc identity[T](a:T):auto=
  787. counter.inc
  788. a
  789. block: # concat test
  790. let
  791. s1 = @[1, 2, 3]
  792. s2 = @[4, 5]
  793. s3 = @[6, 7]
  794. total = concat(s1, s2, s3)
  795. assert total == @[1, 2, 3, 4, 5, 6, 7]
  796. block: # count test
  797. let
  798. s1 = @[1, 2, 3, 2]
  799. s2 = @['a', 'b', 'x', 'a']
  800. a1 = [1, 2, 3, 2]
  801. a2 = ['a', 'b', 'x', 'a']
  802. r0 = count(s1, 0)
  803. r1 = count(s1, 1)
  804. r2 = count(s1, 2)
  805. r3 = count(s2, 'y')
  806. r4 = count(s2, 'x')
  807. r5 = count(s2, 'a')
  808. ar0 = count(a1, 0)
  809. ar1 = count(a1, 1)
  810. ar2 = count(a1, 2)
  811. ar3 = count(a2, 'y')
  812. ar4 = count(a2, 'x')
  813. ar5 = count(a2, 'a')
  814. assert r0 == 0
  815. assert r1 == 1
  816. assert r2 == 2
  817. assert r3 == 0
  818. assert r4 == 1
  819. assert r5 == 2
  820. assert ar0 == 0
  821. assert ar1 == 1
  822. assert ar2 == 2
  823. assert ar3 == 0
  824. assert ar4 == 1
  825. assert ar5 == 2
  826. block: # cycle tests
  827. let
  828. a = @[1, 2, 3]
  829. b: seq[int] = @[]
  830. c = [1, 2, 3]
  831. doAssert a.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
  832. doAssert a.cycle(0) == @[]
  833. #doAssert a.cycle(-1) == @[] # will not compile!
  834. doAssert b.cycle(3) == @[]
  835. doAssert c.cycle(3) == @[1, 2, 3, 1, 2, 3, 1, 2, 3]
  836. doAssert c.cycle(0) == @[]
  837. block: # repeat tests
  838. assert repeat(10, 5) == @[10, 10, 10, 10, 10]
  839. assert repeat(@[1,2,3], 2) == @[@[1,2,3], @[1,2,3]]
  840. assert repeat([1,2,3], 2) == @[[1,2,3], [1,2,3]]
  841. block: # deduplicates test
  842. let
  843. dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
  844. dup2 = @["a", "a", "c", "d", "d"]
  845. dup3 = [1, 1, 3, 4, 2, 2, 8, 1, 4]
  846. dup4 = ["a", "a", "c", "d", "d"]
  847. unique1 = deduplicate(dup1)
  848. unique2 = deduplicate(dup2)
  849. unique3 = deduplicate(dup3)
  850. unique4 = deduplicate(dup4)
  851. unique5 = deduplicate(dup1.sorted, true)
  852. unique6 = deduplicate(dup2, true)
  853. unique7 = deduplicate(dup3.sorted, true)
  854. unique8 = deduplicate(dup4, true)
  855. assert unique1 == @[1, 3, 4, 2, 8]
  856. assert unique2 == @["a", "c", "d"]
  857. assert unique3 == @[1, 3, 4, 2, 8]
  858. assert unique4 == @["a", "c", "d"]
  859. assert unique5 == @[1, 2, 3, 4, 8]
  860. assert unique6 == @["a", "c", "d"]
  861. assert unique7 == @[1, 2, 3, 4, 8]
  862. assert unique8 == @["a", "c", "d"]
  863. block: # zip test
  864. let
  865. short = @[1, 2, 3]
  866. long = @[6, 5, 4, 3, 2, 1]
  867. words = @["one", "two", "three"]
  868. ashort = [1, 2, 3]
  869. along = [6, 5, 4, 3, 2, 1]
  870. awords = ["one", "two", "three"]
  871. zip1 = zip(short, long)
  872. zip2 = zip(short, words)
  873. zip3 = zip(ashort, along)
  874. zip4 = zip(ashort, awords)
  875. zip5 = zip(ashort, words)
  876. assert zip1 == @[(1, 6), (2, 5), (3, 4)]
  877. assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
  878. assert zip3 == @[(1, 6), (2, 5), (3, 4)]
  879. assert zip4 == @[(1, "one"), (2, "two"), (3, "three")]
  880. assert zip5 == @[(1, "one"), (2, "two"), (3, "three")]
  881. assert zip1[2].b == 4
  882. assert zip2[2].b == "three"
  883. assert zip3[2].b == 4
  884. assert zip4[2].b == "three"
  885. assert zip5[2].b == "three"
  886. block: # distribute tests
  887. let numbers = @[1, 2, 3, 4, 5, 6, 7]
  888. doAssert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
  889. doAssert numbers.distribute(6)[0] == @[1, 2]
  890. doAssert numbers.distribute(6)[5] == @[7]
  891. let a = @[1, 2, 3, 4, 5, 6, 7]
  892. doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]]
  893. doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]]
  894. doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]]
  895. doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]]
  896. doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
  897. doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
  898. doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
  899. doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]]
  900. doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]]
  901. doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]]
  902. doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]]
  903. doAssert a.distribute(6, false) == @[
  904. @[1, 2], @[3, 4], @[5, 6], @[7], @[], @[]]
  905. doAssert a.distribute(8, false) == a.distribute(8, true)
  906. doAssert a.distribute(90, false) == a.distribute(90, true)
  907. var b = @[0]
  908. for f in 1 .. 25: b.add(f)
  909. doAssert b.distribute(5, true)[4].len == 5
  910. doAssert b.distribute(5, false)[4].len == 2
  911. block: # map test
  912. let
  913. numbers = @[1, 4, 5, 8, 9, 7, 4]
  914. anumbers = [1, 4, 5, 8, 9, 7, 4]
  915. m1 = map(numbers, proc(x: int): int = 2*x)
  916. m2 = map(anumbers, proc(x: int): int = 2*x)
  917. assert m1 == @[2, 8, 10, 16, 18, 14, 8]
  918. assert m2 == @[2, 8, 10, 16, 18, 14, 8]
  919. block: # apply test
  920. var a = @["1", "2", "3", "4"]
  921. apply(a, proc(x: var string) = x &= "42")
  922. assert a == @["142", "242", "342", "442"]
  923. block: # filter proc test
  924. let
  925. colors = @["red", "yellow", "black"]
  926. acolors = ["red", "yellow", "black"]
  927. f1 = filter(colors, proc(x: string): bool = x.len < 6)
  928. f2 = filter(colors) do (x: string) -> bool : x.len > 5
  929. f3 = filter(acolors, proc(x: string): bool = x.len < 6)
  930. f4 = filter(acolors) do (x: string) -> bool : x.len > 5
  931. assert f1 == @["red", "black"]
  932. assert f2 == @["yellow"]
  933. assert f3 == @["red", "black"]
  934. assert f4 == @["yellow"]
  935. block: # filter iterator test
  936. let numbers = @[1, 4, 5, 8, 9, 7, 4]
  937. let anumbers = [1, 4, 5, 8, 9, 7, 4]
  938. assert toSeq(filter(numbers, proc (x: int): bool = x mod 2 == 0)) ==
  939. @[4, 8, 4]
  940. assert toSeq(filter(anumbers, proc (x: int): bool = x mod 2 == 0)) ==
  941. @[4, 8, 4]
  942. block: # keepIf test
  943. var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1]
  944. keepIf(floats, proc(x: float): bool = x > 10)
  945. assert floats == @[13.0, 12.5, 10.1]
  946. block: # delete tests
  947. let outcome = @[1,1,1,1,1,1,1,1]
  948. var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
  949. dest.delete(3, 8)
  950. assert outcome == dest, """\
  951. Deleting range 3-9 from [1,1,1,2,2,2,2,2,2,1,1,1,1,1]
  952. is [1,1,1,1,1,1,1,1]"""
  953. block: # insert tests
  954. var dest = @[1,1,1,1,1,1,1,1]
  955. let
  956. src = @[2,2,2,2,2,2]
  957. outcome = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
  958. dest.insert(src, 3)
  959. assert dest == outcome, """\
  960. Inserting [2,2,2,2,2,2] into [1,1,1,1,1,1,1,1]
  961. at 3 is [1,1,1,2,2,2,2,2,2,1,1,1,1,1]"""
  962. block: # filterIt test
  963. let
  964. temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44]
  965. acceptable = filterIt(temperatures, it < 50 and it > -10)
  966. notAcceptable = filterIt(temperatures, it > 50 or it < -10)
  967. assert acceptable == @[-2.0, 24.5, 44.31]
  968. assert notAcceptable == @[-272.15, 99.9, -113.44]
  969. block: # keepItIf test
  970. var candidates = @["foo", "bar", "baz", "foobar"]
  971. keepItIf(candidates, it.len == 3 and it[0] == 'b')
  972. assert candidates == @["bar", "baz"]
  973. block: # all
  974. let
  975. numbers = @[1, 4, 5, 8, 9, 7, 4]
  976. anumbers = [1, 4, 5, 8, 9, 7, 4]
  977. len0seq : seq[int] = @[]
  978. assert all(numbers, proc (x: int): bool = return x < 10) == true
  979. assert all(numbers, proc (x: int): bool = return x < 9) == false
  980. assert all(len0seq, proc (x: int): bool = return false) == true
  981. assert all(anumbers, proc (x: int): bool = return x < 10) == true
  982. assert all(anumbers, proc (x: int): bool = return x < 9) == false
  983. block: # allIt
  984. let
  985. numbers = @[1, 4, 5, 8, 9, 7, 4]
  986. anumbers = [1, 4, 5, 8, 9, 7, 4]
  987. len0seq : seq[int] = @[]
  988. assert allIt(numbers, it < 10) == true
  989. assert allIt(numbers, it < 9) == false
  990. assert allIt(len0seq, false) == true
  991. assert allIt(anumbers, it < 10) == true
  992. assert allIt(anumbers, it < 9) == false
  993. block: # any
  994. let
  995. numbers = @[1, 4, 5, 8, 9, 7, 4]
  996. anumbers = [1, 4, 5, 8, 9, 7, 4]
  997. len0seq : seq[int] = @[]
  998. assert any(numbers, proc (x: int): bool = return x > 8) == true
  999. assert any(numbers, proc (x: int): bool = return x > 9) == false
  1000. assert any(len0seq, proc (x: int): bool = return true) == false
  1001. assert any(anumbers, proc (x: int): bool = return x > 8) == true
  1002. assert any(anumbers, proc (x: int): bool = return x > 9) == false
  1003. block: # anyIt
  1004. let
  1005. numbers = @[1, 4, 5, 8, 9, 7, 4]
  1006. anumbers = [1, 4, 5, 8, 9, 7, 4]
  1007. len0seq : seq[int] = @[]
  1008. assert anyIt(numbers, it > 8) == true
  1009. assert anyIt(numbers, it > 9) == false
  1010. assert anyIt(len0seq, true) == false
  1011. assert anyIt(anumbers, it > 8) == true
  1012. assert anyIt(anumbers, it > 9) == false
  1013. block: # toSeq test
  1014. block:
  1015. let
  1016. numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
  1017. odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
  1018. if x mod 2 == 1:
  1019. result = true)
  1020. assert odd_numbers == @[1, 3, 5, 7, 9]
  1021. block:
  1022. doAssert [1,2].toSeq == @[1,2]
  1023. doAssert @[1,2].toSeq == @[1,2]
  1024. doAssert @[1,2].toSeq == @[1,2]
  1025. doAssert toSeq(@[1,2]) == @[1,2]
  1026. block:
  1027. iterator myIter(seed:int):auto=
  1028. for i in 0..<seed:
  1029. yield i
  1030. doAssert toSeq(myIter(2)) == @[0, 1]
  1031. block:
  1032. iterator myIter():auto{.inline.}=
  1033. yield 1
  1034. yield 2
  1035. doAssert myIter.toSeq == @[1,2]
  1036. doAssert toSeq(myIter) == @[1,2]
  1037. block:
  1038. iterator myIter():int {.closure.} =
  1039. yield 1
  1040. yield 2
  1041. doAssert myIter.toSeq == @[1,2]
  1042. doAssert toSeq(myIter) == @[1,2]
  1043. block:
  1044. proc myIter():auto=
  1045. iterator ret():int{.closure.}=
  1046. yield 1
  1047. yield 2
  1048. result = ret
  1049. doAssert myIter().toSeq == @[1,2]
  1050. doAssert toSeq(myIter()) == @[1,2]
  1051. block:
  1052. proc myIter(n:int):auto=
  1053. var counter = 0
  1054. iterator ret():int{.closure.}=
  1055. while counter<n:
  1056. yield counter
  1057. counter.inc
  1058. result = ret
  1059. block:
  1060. let myIter3 = myIter(3)
  1061. doAssert myIter3.toSeq == @[0,1,2]
  1062. block:
  1063. let myIter3 = myIter(3)
  1064. doAssert toSeq(myIter3) == @[0,1,2]
  1065. block:
  1066. # makes sure this does not hang forever
  1067. doAssert myIter(3).toSeq == @[0,1,2]
  1068. doAssert toSeq(myIter(3)) == @[0,1,2]
  1069. block:
  1070. # tests https://github.com/nim-lang/Nim/issues/7187
  1071. counter = 0
  1072. let ret = toSeq(@[1, 2, 3].identity().filter(proc (x: int): bool = x < 3))
  1073. doAssert ret == @[1, 2]
  1074. doAssert counter == 1
  1075. block: # foldl tests
  1076. let
  1077. numbers = @[5, 9, 11]
  1078. addition = foldl(numbers, a + b)
  1079. subtraction = foldl(numbers, a - b)
  1080. multiplication = foldl(numbers, a * b)
  1081. words = @["nim", "is", "cool"]
  1082. concatenation = foldl(words, a & b)
  1083. assert addition == 25, "Addition is (((5)+9)+11)"
  1084. assert subtraction == -15, "Subtraction is (((5)-9)-11)"
  1085. assert multiplication == 495, "Multiplication is (((5)*9)*11)"
  1086. assert concatenation == "nimiscool"
  1087. block: # foldr tests
  1088. let
  1089. numbers = @[5, 9, 11]
  1090. addition = foldr(numbers, a + b)
  1091. subtraction = foldr(numbers, a - b)
  1092. multiplication = foldr(numbers, a * b)
  1093. words = @["nim", "is", "cool"]
  1094. concatenation = foldr(words, a & b)
  1095. assert addition == 25, "Addition is (5+(9+(11)))"
  1096. assert subtraction == 7, "Subtraction is (5-(9-(11)))"
  1097. assert multiplication == 495, "Multiplication is (5*(9*(11)))"
  1098. assert concatenation == "nimiscool"
  1099. block: # mapIt + applyIt test
  1100. counter = 0
  1101. var
  1102. nums = @[1, 2, 3, 4]
  1103. strings = nums.identity.mapIt($(4 * it))
  1104. doAssert counter == 1
  1105. nums.applyIt(it * 3)
  1106. assert nums[0] + nums[3] == 15
  1107. assert strings[2] == "12"
  1108. block: # newSeqWith tests
  1109. var seq2D = newSeqWith(4, newSeq[bool](2))
  1110. seq2D[0][0] = true
  1111. seq2D[1][0] = true
  1112. seq2D[0][1] = true
  1113. doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
  1114. block: # mapLiterals tests
  1115. let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
  1116. doAssert x is array[4, int]
  1117. doAssert mapLiterals((1, ("abc"), 2), float, nested=false) == (float(1), "abc", float(2))
  1118. doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2")
  1119. block: # mapIt with openArray
  1120. counter = 0
  1121. proc foo(x: openArray[int]): seq[int] = x.mapIt(it * 10)
  1122. doAssert foo([identity(1),identity(2)]) == @[10, 20]
  1123. doAssert counter == 2
  1124. block: # mapIt with direct openArray
  1125. proc foo1(x: openArray[int]): seq[int] = x.mapIt(it * 10)
  1126. counter = 0
  1127. doAssert foo1(openArray[int]([identity(1),identity(2)])) == @[10,20]
  1128. doAssert counter == 2
  1129. # Corner cases (openArray litterals should not be common)
  1130. template foo2(x: openArray[int]): seq[int] = x.mapIt(it * 10)
  1131. counter = 0
  1132. doAssert foo2(openArray[int]([identity(1),identity(2)])) == @[10,20]
  1133. # TODO: this fails; not sure how to fix this case
  1134. # doAssert counter == 2
  1135. counter = 0
  1136. doAssert openArray[int]([identity(1), identity(2)]).mapIt(it) == @[1,2]
  1137. # ditto
  1138. # doAssert counter == 2
  1139. block: # mapIt empty test, see https://github.com/nim-lang/Nim/pull/8584#pullrequestreview-144723468
  1140. # NOTE: `[].mapIt(it)` is illegal, just as `let a = @[]` is (lacks type
  1141. # of elements)
  1142. doAssert: not compiles(mapIt(@[], it))
  1143. doAssert: not compiles(mapIt([], it))
  1144. doAssert newSeq[int](0).mapIt(it) == @[]
  1145. block: # mapIt redifinition check, see https://github.com/nim-lang/Nim/issues/8580
  1146. let s2 = [1,2].mapIt(it)
  1147. doAssert s2 == @[1,2]
  1148. block:
  1149. counter = 0
  1150. doAssert [1,2].identity().mapIt(it*2).mapIt(it*10) == @[20, 40]
  1151. # https://github.com/nim-lang/Nim/issues/7187 test case
  1152. doAssert counter == 1
  1153. block: # mapIt with invalid RHS for `let` (#8566)
  1154. type X = enum
  1155. A, B
  1156. doAssert mapIt(X, $it) == @["A", "B"]
  1157. block:
  1158. # bug #9093
  1159. let inp = "a:b,c:d"
  1160. let outp = inp.split(",").mapIt(it.split(":"))
  1161. doAssert outp == @[@["a", "b"], @["c", "d"]]
  1162. when not defined(testing):
  1163. echo "Finished doc tests"