summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-01-16 20:02:55 +0100
committerAraq <rumpf_a@web.de>2013-01-16 20:02:55 +0100
commita4b1ca3306afb277c0d0e7aacede2d6c63f13aeb (patch)
tree5d83d400ee1f06ef996f6acb74ae66e7399e5d1d /lib
parente353737e34eeba6056737fa9e895f69bd56fb3af (diff)
parent10d995c2908e2c4a2e8faeb7bf92e9f38987c85a (diff)
downloadNim-a4b1ca3306afb277c0d0e7aacede2d6c63f13aeb.tar.gz
fixed merge conflict
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/collections/sequtils.nim164
-rwxr-xr-xlib/pure/collections/tables.nim46
-rwxr-xr-xlib/pure/json.nim9
-rwxr-xr-xlib/system.nim6
-rwxr-xr-xlib/wrappers/lua/lua.nim39
5 files changed, 237 insertions, 27 deletions
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 0fda5700e..e4ea22830 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -9,8 +9,16 @@
 
 ## :Author: Alex Mitchell
 ##
-## This module implements operations for the built-in `seq`:idx: type
-## which were inspired by functional programming languages.
+## This module implements operations for the built-in `seq`:idx: type which
+## were inspired by functional programming languages. If you are looking for
+## the typical `map` function which applies a function to every element in a
+## sequence, it already exists as the `each` proc in the `system
+## <system.html>`_ module in both mutable and immutable styles.
+##
+## Also, for functional style programming you may want to pass `anonymous procs
+## <manual.html#anonymous-procs>`_ to procs like ``filter`` to reduce typing.
+## Anonymous procs can use `the special do notation <manual.html#do-notation>`_
+## which is more convenient in certain situations.
 ##
 ## **Note**: This interface will change as soon as the compiler supports
 ## closures and proper coroutines.
@@ -19,7 +27,17 @@ when not defined(nimhygiene):
   {.pragma: dirty.}
 
 proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
-  ## Takes several sequences' items and returns them inside of one sequence.
+  ## Takes several sequences' items and returns them inside a new sequence.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let
+  ##     s1 = @[1, 2, 3]
+  ##     s2 = @[4, 5]
+  ##     s3 = @[6, 7]
+  ##     total = concat(s1, s2, s3)
+  ##   assert total == @[1, 2, 3, 4, 5, 6, 7]
   var L = 0
   for seqitm in items(seqs): inc(L, len(seqitm))
   newSeq(result, L)
@@ -30,14 +48,42 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
       inc(i)
 
 proc distnct*[T](seq1: seq[T]): seq[T] =
-  ## Removes duplicates from a sequence and returns it.
+  ## Returns a new sequence without duplicates.
+  ##
+  ## This proc is `misspelled` on purpose to avoid a clash with the keyword
+  ## ``distinct`` used to `define a derived type incompatible with its base
+  ## type <manual.html#distinct-type>`_. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let
+  ##     dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
+  ##     dup2 = @["a", "a", "c", "d", "d"]
+  ##     unique1 = distnct(dup1)
+  ##     unique2 = distnct(dup2)
+  ##   assert unique1 == @[1, 3, 4, 2, 8]
+  ##   assert unique2 == @["a", "c", "d"]
   result = @[]
   for itm in items(seq1):
     if not result.contains(itm): result.add(itm)
     
 proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
-  ## Combines two sequences. If one sequence is too short,
-  ## the remaining items in the longer sequence are discarded.
+  ## Returns a new sequence with a combination of the two input sequences.
+  ##
+  ## For convenience you can access the returned tuples through the named
+  ## fields `a` and `b`. If one sequence is shorter, the remaining items in the
+  ## longer sequence are discarded. Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let
+  ##     short = @[1, 2, 3]
+  ##     long = @[6, 5, 4, 3, 2, 1]
+  ##     words = @["one", "two", "three"]
+  ##     zip1 = zip(short, long)
+  ##     zip2 = zip(short, words)
+  ##   assert zip1 == @[(1, 6), (2, 5), (3, 4)]
+  ##   assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
+  ##   assert zip1[2].b == 4
+  ##   assert zip2[2].b == "three"
   var m = min(seq1.len, seq2.len)
   newSeq(result, m)
   for i in 0 .. m-1: result[i] = (seq1[i], seq2[i])
@@ -45,18 +91,44 @@ proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
 iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T =
   ## Iterates through a sequence and yields every item that fulfills the
   ## predicate.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let numbers = @[1, 4, 5, 8, 9, 7, 4]
+  ##   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]
 
 proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] =
-  ## Returns all items in a sequence that fulfilled the predicate.
+  ## Returns a new sequence with all the items that fulfilled the predicate.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let
+  ##     colors = @["red", "yellow", "black"]
+  ##     f1 = filter(colors, proc(x: string): bool = x.len < 6)
+  ##     f2 = filter(colors) do (x: string) -> bool : x.len > 5
+  ##   assert f1 == @["red", "black"]
+  ##   assert f2 == @["yellow"]
   accumulateResult(filter(seq1, pred))
 
 template filterIt*(seq1, pred: expr): expr {.immediate, dirty.} =
-  ## Finds a specific item in a sequence as long as the 
-  ## predicate returns true. The predicate needs to be an expression
-  ## containing ``it``: ``filterIt("abcxyz", it == 'x')``.
+  ## Returns a new sequence with all the items that fulfilled the predicate.
+  ##
+  ## Unlike the `proc` version, the predicate needs to be an expression using
+  ## the ``it`` variable for testing, like: ``filterIt("abcxyz", it == 'x')``.
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##    let
+  ##      temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44]
+  ##      acceptable = filterIt(temperatures, it < 50 and it > -10)
+  ##    assert acceptable == @[-2.0, 24.5, 44.31]
   block:
     var result: type(seq1) = @[]
     for it in items(seq1):
@@ -65,7 +137,79 @@ template filterIt*(seq1, pred: expr): expr {.immediate, dirty.} =
 
 template toSeq*(iter: expr): expr {.immediate.} =
   ## Transforms any iterator into a sequence.
+  ##
+  ## Example:
+  ##
+  ## .. code-block:: nimrod
+  ##   let
+  ##     numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
+  ##     odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
+  ##       if x mod 2 == 1:
+  ##         result = true)
+  ##   assert odd_numbers == @[1, 3, 5, 7, 9]
+  ##
   var result {.gensym.}: seq[type(iter)] = @[]
   for x in iter: add(result, x)
   result
 
+when isMainModule:
+  import strutils
+  proc toStr(x: int): string {.procvar.} = $x
+  # concat test
+  let
+    s1 = @[1, 2, 3]
+    s2 = @[4, 5]
+    s3 = @[6, 7]
+    total = concat(s1, s2, s3)
+  assert total == @[1, 2, 3, 4, 5, 6, 7]
+
+  # duplicates test
+  let
+    dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
+    dup2 = @["a", "a", "c", "d", "d"]
+    unique1 = distnct(dup1)
+    unique2 = distnct(dup2)
+  assert unique1 == @[1, 3, 4, 2, 8]
+  assert unique2 == @["a", "c", "d"]
+
+  # zip test
+  let
+    short = @[1, 2, 3]
+    long = @[6, 5, 4, 3, 2, 1]
+    words = @["one", "two", "three"]
+    zip1 = zip(short, long)
+    zip2 = zip(short, words)
+  assert zip1 == @[(1, 6), (2, 5), (3, 4)]
+  assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
+  assert zip1[2].b == 4
+  assert zip2[2].b == "three"
+
+  # filter proc test
+  let
+    colors = @["red", "yellow", "black"]
+    f1 = filter(colors, proc(x: string): bool = x.len < 6)
+    f2 = filter(colors) do (x: string) -> bool : x.len > 5
+  assert f1 == @["red", "black"]
+  assert f2 == @["yellow"]
+
+  # filter iterator test
+  let numbers = @[1, 4, 5, 8, 9, 7, 4]
+  for n in filter(numbers, proc (x: int): bool = x mod 2 == 0):
+    echo($n)
+  # echoes 4, 8, 4 in separate lines
+
+  # filterIt test
+  let
+    temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44]
+    acceptable = filterIt(temperatures, it < 50 and it > -10)
+  assert acceptable == @[-2.0, 24.5, 44.31]
+
+  # toSeq test
+  let
+    numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
+    odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
+      if x mod 2 == 1:
+        result = true)
+  assert odd_numbers == @[1, 3, 5, 7, 9]
+
+  echo "Finished doc tests"
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index fc394d1f8..4290af08a 100755
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -308,6 +308,52 @@ proc `$`*[A, B](t: TOrderedTable[A, B]): string =
   ## The `$` operator for ordered hash tables.
   dollarImpl()
 
+proc sort*[A, B](t: var TOrderedTable[A, B], 
+                 cmp: proc (x,y: tuple[key: A, val: B]): int) =
+  ## sorts `t` according to `cmp`. This modifies the internal list
+  ## that kept the insertion order, so insertion order is lost after this
+  ## call but key lookup and insertions remain possible after `sort` (in
+  ## contrast to the `sort` for count tables).
+  var list = t.first
+  var
+    p, q, e, tail, oldhead: int
+    nmerges, psize, qsize, i: int
+  if t.counter == 0: return
+  var insize = 1
+  while true:
+    p = list; oldhead = list
+    list = -1; tail = -1; nmerges = 0
+    while p >= 0:
+      inc(nmerges)
+      q = p
+      psize = 0
+      i = 0
+      while i < insize:
+        inc(psize)
+        q = t.data[q].next
+        if q < 0: break 
+        inc(i)
+      qsize = insize
+      while psize > 0 or (qsize > 0 and q >= 0):
+        if psize == 0:
+          e = q; q = t.data[q].next; dec(qsize)
+        elif qsize == 0 or q < 0:
+          e = p; p = t.data[p].next; dec(psize)
+        elif cmp((t.data[p].key, t.data[p].val), 
+                 (t.data[q].key, t.data[q].val)) <= 0:
+          e = p; p = t.data[p].next; dec(psize)
+        else:
+          e = q; q = t.data[q].next; dec(qsize)
+        if tail >= 0: t.data[tail].next = e
+        else: list = e
+        tail = e
+      p = q
+    t.data[tail].next = -1
+    if nmerges <= 1: break
+    insize = insize * 2
+  t.first = list
+  t.last = tail
+
 # ------------------------------ count tables -------------------------------
 
 type
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index cee135f08..cca1e4a70 100755
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -541,6 +541,11 @@ proc newJString*(s: String): PJsonNode =
   result.kind = JString
   result.str = s
 
+proc newJStringMove(s: String): PJsonNode =
+  new(result)
+  result.kind = JString
+  shallowCopy(result.str, s)
+
 proc newJInt*(n: biggestInt): PJsonNode =
   ## Creates a new `JInt PJsonNode`.
   new(result)
@@ -809,7 +814,9 @@ proc parseJson(p: var TJsonParser): PJsonNode =
   ## Parses JSON from a JSON Parser `p`.
   case p.tok
   of tkString:
-    result = newJString(p.a)
+    # we capture 'p.a' here, so we need to give it a fresh buffer afterwards:
+    result = newJStringMove(p.a)
+    p.a = ""
     discard getTok(p)
   of tkInt:
     result = newJInt(parseBiggestInt(p.a))
diff --git a/lib/system.nim b/lib/system.nim
index 3d17b1d6d..26e5ac228 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1461,14 +1461,14 @@ proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
   setLen(s, L)
 
 proc each*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}): seq[S] = 
-  ## The well-known ``map`` operation from functional programming. Applies
+  ## The well-known `map`:idx: operation from functional programming. Applies
   ## `op` to every item in `data` and returns the result as a sequence.
   newSeq(result, data.len)
   for i in 0..data.len-1: result[i] = op(data[i])
 
 proc each*[T](data: var openArray[T], op: proc (x: var T) {.closure.}) =
-  ## The well-known ``map`` operation from functional programming. Applies
-  ## `op` to every item in `data`.
+  ## The well-known `map`:idx: operation from functional programming. Applies
+  ## `op` to every item in `data` modifying it directly.
   for i in 0..data.len-1: op(data[i])
 
 iterator fields*[T: tuple](x: T): TObject {.
diff --git a/lib/wrappers/lua/lua.nim b/lib/wrappers/lua/lua.nim
index 000e09993..0346c4285 100755
--- a/lib/wrappers/lua/lua.nim
+++ b/lib/wrappers/lua/lua.nim
@@ -35,19 +35,32 @@
 #**   In french or in english
 #
 
-when defined(MACOSX): 
-  const 
-    NAME* = "liblua(|5.2|5.1|5.0).dylib"
-    LIB_NAME* = "liblua(|5.2|5.1|5.0).dylib"
-elif defined(UNIX): 
-  const 
-    NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
-    LIB_NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
-else: 
-  const 
-    NAME* = "lua(|5.2|5.1|5.0).dll"
-    LIB_NAME* = "lua(|5.2|5.1|5.0).dll"
-
+when defined(useLuajit):
+  when defined(MACOSX):
+    const
+      NAME* = "libluajit.dylib"
+      LIB_NAME* = "libluajit.dylib"
+  elif defined(UNIX):
+    const
+      NAME* = "libluajit.so(|.0)"
+      LIB_NAME* = "libluajit.so(|.0)"
+  else:
+    const
+      NAME* = "luajit.dll"
+      LIB_NAME* = "luajit.dll"
+else:
+  when defined(MACOSX):
+    const
+      NAME* = "liblua(|5.2|5.1|5.0).dylib"
+      LIB_NAME* = "liblua(|5.2|5.1|5.0).dylib"
+  elif defined(UNIX):
+    const
+      NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
+      LIB_NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
+  else:
+    const 
+      NAME* = "lua(|5.2|5.1|5.0).dll"
+      LIB_NAME* = "lua(|5.2|5.1|5.0).dll"
 
 const 
   VERSION* = "Lua 5.1"