Merge pull request #3937 from oderwat/hara-foldl
Fixes foldl() and foldr() + foldl() with start parameter
This commit is contained in:
commit
7281b66a4f
1 changed files with 37 additions and 10 deletions
|
|
@ -508,13 +508,39 @@ template foldl*(sequence, operation: expr): expr =
|
||||||
## assert subtraction == -15, "Subtraction is (((5)-9)-11)"
|
## assert subtraction == -15, "Subtraction is (((5)-9)-11)"
|
||||||
## assert multiplication == 495, "Multiplication is (((5)*9)*11)"
|
## assert multiplication == 495, "Multiplication is (((5)*9)*11)"
|
||||||
## assert concatenation == "nimiscool"
|
## assert concatenation == "nimiscool"
|
||||||
assert sequence.len > 0, "Can't fold empty sequences"
|
let s = sequence
|
||||||
var result {.gensym.}: type(sequence[0])
|
assert s.len > 0, "Can't fold empty sequences"
|
||||||
result = sequence[0]
|
var result {.gensym.}: type(s[0])
|
||||||
for i in 1..<sequence.len:
|
result = s[0]
|
||||||
|
for i in 1..<s.len:
|
||||||
let
|
let
|
||||||
a {.inject.} = result
|
a {.inject.} = result
|
||||||
b {.inject.} = sequence[i]
|
b {.inject.} = s[i]
|
||||||
|
result = operation
|
||||||
|
result
|
||||||
|
|
||||||
|
template foldl*(sequence, operation: expr, first): expr =
|
||||||
|
## Template to fold a sequence from left to right, returning the accumulation.
|
||||||
|
##
|
||||||
|
## This version of ``foldl`` gets a starting parameter. This makes it possible
|
||||||
|
## to accumulate the sequence into a different type than the sequence elements.
|
||||||
|
##
|
||||||
|
## The ``operation`` parameter should be an expression which uses the variables
|
||||||
|
## ``a`` and ``b`` for each step of the fold. The ``first`` parameter is the
|
||||||
|
## start value (the first ``a``) and therefor defines the type of the result.
|
||||||
|
## Example:
|
||||||
|
##
|
||||||
|
## .. code-block::
|
||||||
|
## let
|
||||||
|
## numbers = @[0, 8, 1, 5]
|
||||||
|
## digits = foldl(numbers, a & (chr(b + ord('0'))), "")
|
||||||
|
## assert digits == "0815"
|
||||||
|
var result {.gensym.}: type(first)
|
||||||
|
result = first
|
||||||
|
for x in items(sequence):
|
||||||
|
let
|
||||||
|
a {.inject.} = result
|
||||||
|
b {.inject.} = x
|
||||||
result = operation
|
result = operation
|
||||||
result
|
result
|
||||||
|
|
||||||
|
|
@ -544,12 +570,13 @@ template foldr*(sequence, operation: expr): expr =
|
||||||
## assert subtraction == 7, "Subtraction is (5-(9-(11)))"
|
## assert subtraction == 7, "Subtraction is (5-(9-(11)))"
|
||||||
## assert multiplication == 495, "Multiplication is (5*(9*(11)))"
|
## assert multiplication == 495, "Multiplication is (5*(9*(11)))"
|
||||||
## assert concatenation == "nimiscool"
|
## assert concatenation == "nimiscool"
|
||||||
assert sequence.len > 0, "Can't fold empty sequences"
|
let s = sequence
|
||||||
var result {.gensym.}: type(sequence[0])
|
assert s.len > 0, "Can't fold empty sequences"
|
||||||
result = sequence[sequence.len - 1]
|
var result {.gensym.}: type(s[0])
|
||||||
for i in countdown(sequence.len - 2, 0):
|
result = sequence[s.len - 1]
|
||||||
|
for i in countdown(s.len - 2, 0):
|
||||||
let
|
let
|
||||||
a {.inject.} = sequence[i]
|
a {.inject.} = s[i]
|
||||||
b {.inject.} = result
|
b {.inject.} = result
|
||||||
result = operation
|
result = operation
|
||||||
result
|
result
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue