From 75097e2981e470197fa5649557875a9f60385973 Mon Sep 17 00:00:00 2001 From: Peter Mora Date: Mon, 5 Oct 2015 22:41:54 +0200 Subject: sequtils related changes --- examples/maximum.nim | 2 +- lib/pure/collections/sequtils.nim | 205 +++++++++++++++++++++++++------ lib/system.nim | 47 ------- tests/closure/tclosure4.nim | 2 +- tests/collections/tapply.nim | 7 ++ tests/collections/tmapit.nim | 28 +++++ tests/generics/tinferredgenericprocs.nim | 1 + tests/generics/tmap_auto.nim | 2 +- tests/overload/toverprc.nim | 2 +- tests/parser/tcommand_as_expr.nim | 1 + tests/template/twrongmapit.nim | 2 +- 11 files changed, 211 insertions(+), 88 deletions(-) create mode 100644 tests/collections/tapply.nim create mode 100644 tests/collections/tmapit.nim diff --git a/examples/maximum.nim b/examples/maximum.nim index aa3fe375a..6552a8144 100644 --- a/examples/maximum.nim +++ b/examples/maximum.nim @@ -1,6 +1,6 @@ # Test high level features -import strutils +import strutils, sequtils echo "Give a list of numbers (separated by spaces): " stdin.readLine.split.map(parseInt).max.`$`.echo(" is the maximum!") diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index e6ea19a6b..6e51b453e 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -47,7 +47,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] = result[i] = itm inc(i) -proc repeat*[T](s: seq[T], n: Natural): seq[T] = +proc cycle*[T](s: seq[T], n: Natural): seq[T] = ## Returns a new sequence with the items of `s` repeated `n` times. ## ## Example: @@ -56,15 +56,29 @@ proc repeat*[T](s: seq[T], n: Natural): seq[T] = ## ## let ## s = @[1, 2, 3] - ## total = s.repeat(3) + ## total = s.cycle(3) ## assert total == @[1, 2, 3, 1, 2, 3, 1, 2, 3] result = newSeq[T](n * s.len) var o = 0 - for x in 1..n: + for x in 0.. ["1", "2", "3", "4"] + ## map(a, proc(x: var string) = x &= "42") + ## echo repr(a) + ## # --> ["142", "242", "342", "442"] + ## **Deprecated since version 0.12.0:** Use the ``apply`` proc instead. + for i in 0..data.len-1: op(data[i]) + +proc apply*[T](data: var seq[T], op: proc (x: var T) {.closure.}) + {.inline.} = + ## Applies `op` to every item in `data` modifying it directly. + ## + ## Note that this requires your input and output types to + ## be the same, since they are modified in-place. + ## The parameter function takes a ``var T`` type parameter. + ## Example: + ## + ## .. code-block:: nim + ## var a = @["1", "2", "3", "4"] + ## echo repr(a) + ## # --> ["1", "2", "3", "4"] + ## map(a, proc(x: var string) = x &= "42") + ## echo repr(a) + ## # --> ["142", "242", "342", "442"] + ## + for i in 0..data.len-1: op(data[i]) + +proc apply*[T](data: var seq[T], op: proc (x: T): T {.closure.}) + {.inline.} = + ## Applies `op` to every item in `data` modifying it directly. + ## + ## Note that this requires your input and output types to + ## be the same, since they are modified in-place. + ## The parameter function takes and returns a ``T`` type variable. + ## Example: + ## + ## .. code-block:: nim + ## var a = @["1", "2", "3", "4"] + ## echo repr(a) + ## # --> ["1", "2", "3", "4"] + ## map(a, proc(x: string): string = x & "42") + ## echo repr(a) + ## # --> ["142", "242", "342", "442"] + ## + for i in 0..data.len-1: data[i] = op(data[i]) + iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T = ## Iterates through a sequence and yields every item that fulfills the @@ -181,11 +266,12 @@ iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T = ## for n in filter(numbers, proc (x: int): bool = x mod 2 == 0): ## echo($n) ## # echoes 4, 8, 4 in separate lines - for i in countup(0, len(seq1)-1): - var item = seq1[i] - if pred(item): yield seq1[i] + for i in 0.. bool : x.len > 5 ## assert f1 == @["red", "black"] ## assert f2 == @["yellow"] - accumulateResult(filter(seq1, pred)) + result = newSeq[T]() + for i in 0.. 50 or it < -10) ## assert acceptable == @[-2.0, 24.5, 44.31] ## assert notAcceptable == @[-272.15, 99.9, -113.44] - var result {.gensym.}: type(seq1) = @[] + var result {.gensym.} = newSeq[type(seq1[0])]() for it {.inject.} in items(seq1): if pred: result.add(it) result -template keepItIf*(varSeq, pred: expr) = +template keepItIf*(varSeq: seq, pred: expr) = ## Convenience template around the ``keepIf`` proc to reduce typing. ## ## Unlike the `proc` version, the predicate needs to be an expression using @@ -303,12 +393,12 @@ template keepItIf*(varSeq, pred: expr) = let it {.inject.} = varSeq[i] if pred: if pos != i: - varSeq[pos] = varSeq[i] + shallowCopy(varSeq[pos], varSeq[i]) inc(pos) setLen(varSeq, pos) -template toSeq*(iter: expr): expr {.immediate.} = +template toSeq*(iter: expr): expr = ## Transforms any iterator into a sequence. ## ## Example: @@ -320,14 +410,19 @@ template toSeq*(iter: expr): expr {.immediate.} = ## if x mod 2 == 1: ## result = true) ## assert odd_numbers == @[1, 3, 5, 7, 9] - ## - ## **Note**: Since this is an immediate macro, you cannot always invoke this - ## as ``x.toSeq``, depending on the ``x``. - ## See `this `_ - ## for an explanation. - var result {.gensym.}: seq[type(iter)] = @[] - for x in iter: add(result, x) - result + + when compiles(iter.len): + var i = 0 + var result = newSeq[type(iter)](iter.len) + for x in iter: + result[i] = x + inc i + result + else: + var result: seq[type(iter)] = @[] + for x in iter: + result.add(x) + result template foldl*(sequence, operation: expr): expr = ## Template to fold a sequence from left to right, returning the accumulation. @@ -358,7 +453,7 @@ template foldl*(sequence, operation: expr): expr = assert sequence.len > 0, "Can't fold empty sequences" var result {.gensym.}: type(sequence[0]) result = sequence[0] - for i in countup(1, sequence.len - 1): + for i in 1.. ["1", "2", "3", "4"] - ## map(a, proc(x: var string) = x &= "42") - ## echo repr(a) - ## # --> ["142", "242", "342", "442"] - for i in 0..data.len-1: op(data[i]) - iterator fields*[T: tuple|object](x: T): RootObj {. magic: "Fields", noSideEffect.} ## iterates over every field of `x`. Warning: This really transforms diff --git a/tests/closure/tclosure4.nim b/tests/closure/tclosure4.nim index 8e08376b6..10c7cac54 100644 --- a/tests/closure/tclosure4.nim +++ b/tests/closure/tclosure4.nim @@ -1,5 +1,5 @@ -import json, tables +import json, tables, sequtils proc run(json_params: TTable) = let json_elems = json_params["files"].elems diff --git a/tests/collections/tapply.nim b/tests/collections/tapply.nim new file mode 100644 index 000000000..403321ce1 --- /dev/null +++ b/tests/collections/tapply.nim @@ -0,0 +1,7 @@ +import sequtils + +var x = @[1, 2, 3] +x.apply(proc(x: var int) = x = x+10) +x.apply(proc(x: int): int = x+100) +x.applyIt(it+5000) +doAssert x == @[5111, 5112, 5113] diff --git a/tests/collections/tmapit.nim b/tests/collections/tmapit.nim new file mode 100644 index 000000000..067561882 --- /dev/null +++ b/tests/collections/tmapit.nim @@ -0,0 +1,28 @@ +import sequtils + +var x = @[1, 2, 3] +# This mapIt call will run with preallocation because ``len`` is available. +var y = x.mapIt($(it+10)) +doAssert y == @["11", "12", "13"] + +type structureWithoutLen = object + a: array[5, int] + +iterator items(s: structureWithoutLen): int {.inline.} = + yield s.a[0] + yield s.a[1] + yield s.a[2] + yield s.a[3] + yield s.a[4] + +var st: structureWithoutLen +st.a[0] = 0 +st.a[1] = 1 +st.a[2] = 2 +st.a[3] = 3 +st.a[4] = 4 + +# this will run without preallocating the result +# since ``len`` is not available +var r = st.mapIt($(it+10)) +doAssert r == @["10", "11", "12", "13", "14"] diff --git a/tests/generics/tinferredgenericprocs.nim b/tests/generics/tinferredgenericprocs.nim index 5cbeabb94..359c71ba8 100644 --- a/tests/generics/tinferredgenericprocs.nim +++ b/tests/generics/tinferredgenericprocs.nim @@ -5,6 +5,7 @@ discard """ 3''' """ +import sequtils # https://github.com/Araq/Nim/issues/797 proc foo[T](s:T):string = $s diff --git a/tests/generics/tmap_auto.nim b/tests/generics/tmap_auto.nim index dea9b571f..572556722 100644 --- a/tests/generics/tmap_auto.nim +++ b/tests/generics/tmap_auto.nim @@ -1,4 +1,4 @@ -import future +import future, sequtils let x = map(@[1, 2, 3], x => x+10) assert x == @[11, 12, 13] diff --git a/tests/overload/toverprc.nim b/tests/overload/toverprc.nim index 78831f744..112eae096 100644 --- a/tests/overload/toverprc.nim +++ b/tests/overload/toverprc.nim @@ -5,7 +5,7 @@ yay''' # Test overloading of procs when used as function pointers -import strutils +import strutils, sequtils proc parseInt(x: float): int {.noSideEffect.} = discard proc parseInt(x: bool): int {.noSideEffect.} = discard diff --git a/tests/parser/tcommand_as_expr.nim b/tests/parser/tcommand_as_expr.nim index 730e9cbb7..a244c8767 100644 --- a/tests/parser/tcommand_as_expr.nim +++ b/tests/parser/tcommand_as_expr.nim @@ -5,6 +5,7 @@ discard """ 77''' """ #import math +import sequtils proc optarg(x:int, y:int = 0):int = x + 3 * y proc singlearg(x:int):int = 20*x diff --git a/tests/template/twrongmapit.nim b/tests/template/twrongmapit.nim index 0a6d694f6..df695fcd6 100644 --- a/tests/template/twrongmapit.nim +++ b/tests/template/twrongmapit.nim @@ -27,6 +27,6 @@ when ATTEMPT == 0: # bug #1543 import sequtils -(var i = @[""];i).mapIt(it) +(var i = @[""];i).applyIt(it) # now works: echo "##", i[0], "##" -- cgit 1.4.1-2-gfad0 From 6318f77821959f1fbd0c6bd3d04550b6ac926dcc Mon Sep 17 00:00:00 2001 From: Peter Mora Date: Tue, 6 Oct 2015 08:15:00 +0200 Subject: restore {.immediate.} to toSeq --- lib/pure/collections/sequtils.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 6e51b453e..fd012e811 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -398,7 +398,7 @@ template keepItIf*(varSeq: seq, pred: expr) = setLen(varSeq, pos) -template toSeq*(iter: expr): expr = +template toSeq*(iter: expr): expr {.immediate.} = ## Transforms any iterator into a sequence. ## ## Example: -- cgit 1.4.1-2-gfad0 From b284ace099aa2dadfd67c4006ded2f64225e4c09 Mon Sep 17 00:00:00 2001 From: Peter Mora Date: Tue, 6 Oct 2015 08:24:43 +0200 Subject: fixing unittest --- tests/stdlib/tunittest.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim index 4d2a2a340..4b210c23b 100644 --- a/tests/stdlib/tunittest.nim +++ b/tests/stdlib/tunittest.nim @@ -1,4 +1,4 @@ -import unittest +import unittest, sequtils proc doThings(spuds: var int): int = -- cgit 1.4.1-2-gfad0 From e2468fee55a3477a5707ac2d74b329fcb73f4f2b Mon Sep 17 00:00:00 2001 From: Peter Mora Date: Tue, 6 Oct 2015 22:03:43 +0200 Subject: updated news.txt with backward compatibility breaks of sequtils --- web/news.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/web/news.txt b/web/news.txt index 2b6079620..45bbe8c44 100644 --- a/web/news.txt +++ b/web/news.txt @@ -87,7 +87,13 @@ News echo f(0, "abc") - The ``ftpclient`` module is now deprecated in favour of the ``asyncdispatch`` module. - + - In sequtils.nim renamed ``repeat`` function to ``cycle`` (concatenating + a sequence by itself the given times), and also introduced ``repeat``, + which repeats an element the given times. + - The function ``map`` is moved to sequtils.nim. The inplace ``map`` version + is renamed to ``apply``. + - The template ``mapIt`` now doesn't require the result's type parameter. + Also the inplace ``mapIt`` is renamed to ``apply``. Library Additions ----------------- -- cgit 1.4.1-2-gfad0