bugfix: multiple yield statements and loop body vars

This commit is contained in:
Araq 2010-12-13 07:58:35 +01:00
commit 63ac32e6de
13 changed files with 256 additions and 75 deletions

View file

@ -226,21 +226,27 @@ proc push*(s: var TRunningStat, x: float) =
inc(s.n)
# See Knuth TAOCP vol 2, 3rd edition, page 232
if s.n == 1:
s.min = x
s.max = x
s.oldM = x
s.mean = x
s.oldS = 0.0
else:
if s.min > x: s.min = x
if s.max < x: s.max = x
s.mean = s.oldM + (x - s.oldM)/toFloat(s.n)
s.newS = s.oldS + (x - s.oldM)*(x - s.mean)
# set up for next iteration:
s.oldM = s.mean
s.oldS = s.newS
s.sum = s.sum + x
if s.min > x: s.min = x
if s.max < x: s.max = x
proc push*(s: var TRunningStat, x: int) =
## pushes a value `x` for processing. `x` is simply converted to ``float``
## and the other push operation is called.
push(s, toFloat(x))
proc variance*(s: TRunningStat): float =
## computes the current variance of `s`
if s.n > 1: result = s.newS / (toFloat(s.n - 1))

View file

@ -464,6 +464,69 @@ proc align*(s: string, count: int): string {.
else:
result = s
iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
token: string, isSep: bool] =
## Tokenizes the string `s` into substrings.
##
## Substrings are separated by a substring containing only `seps`.
## Examples:
##
## .. code-block:: nimrod
## for word in tokenize(" this is an example "):
## writeln(stdout, word)
##
## Results in:
##
## .. code-block:: nimrod
## (" ", true)
## ("this", false)
## (" ", true)
## ("is", false)
## (" ", true)
## ("an", false)
## (" ", true)
## ("example", false)
## (" ", true)
var i = 0
while true:
var j = i
var isSep = s[j] in seps
while j < s.len and (s[j] in seps) == isSep: inc(j)
if j > i:
yield (copy(s, i, j-1), isSep)
else:
break
i = j
proc wordWrap*(s: string, maxLineWidth = 80,
splitLongWords = true,
seps: set[char] = whitespace,
newLine = "\n"): string {.
noSideEffect, rtl, extern: "nsuWordWrap".} =
## word wraps `s`.
result = ""
var SpaceLeft = maxLineWidth
for word, isSep in tokenize(s, seps):
if len(word) > SpaceLeft:
if splitLongWords and len(word) > maxLineWidth:
result.add(copy(word, 0, spaceLeft-1))
var w = spaceLeft+1
var wordLeft = len(word) - spaceLeft
while wordLeft > 0:
result.add(newLine)
var L = min(maxLineWidth, wordLeft)
SpaceLeft = maxLineWidth - L
result.add(copy(word, w, w+L-1))
inc(w, L)
dec(wordLeft, L)
else:
SpaceLeft = maxLineWidth - len(Word)
result.add(newLine)
result.add(word)
else:
SpaceLeft = SpaceLeft - len(Word)
result.add(word)
proc startsWith*(s, prefix: string): bool {.noSideEffect,
rtl, extern: "nsuStartsWith".} =
## Returns true iff ``s`` starts with ``prefix``.
@ -879,6 +942,7 @@ when isMainModule:
assert align("abc", 4) == " abc"
assert align("a", 0) == "a"
assert align("1232", 6) == " 1232"
echo wordWrap(""" this is a long text -- muchlongerthan10chars and here
it goes""", 10, false)

View file

@ -1099,6 +1099,15 @@ iterator items*(a: cstring): char {.inline.} =
yield a[i]
inc(i)
iterator enumerate*[TContainer, TItem](a: TContainer): tuple[
index: int, item: TItem] {.inline.} =
## iterates over each item of `a` via `items` and yields an additional
## counter/index starting from 0.
var j = 0
for it in items(a):
yield (j, a)
inc j
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".}
@ -1108,20 +1117,20 @@ proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
## Fast check whether `x` is nil. This is sometimes more efficient than
## ``== nil``.
proc `&` *[T](x, y: openArray[T]): seq[T] {.noSideEffect.} =
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
newSeq(result, x.len + y.len)
for i in 0..x.len-1:
result[i] = x[i]
for i in 0..y.len-1:
result[i+x.len] = y[i]
proc `&` *[T](x: openArray[T], y: T): seq[T] {.noSideEffect.} =
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} =
newSeq(result, x.len + 1)
for i in 0..x.len-1:
result[i] = x[i]
result[x.len] = y
proc `&` *[T](x: T, y: openArray[T]): seq[T] {.noSideEffect.} =
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
newSeq(result, y.len + 1)
for i in 0..y.len-1:
result[i] = y[i]