bugfix: multiple yield statements and loop body vars
This commit is contained in:
parent
e7fe8edab3
commit
63ac32e6de
13 changed files with 256 additions and 75 deletions
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue