You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Iterate efficiently over a variadic number of containers.
The loop structure is generated inline at compile-time.
There are no temporary allocation.
Status
The containers can be any number of seq, arrays or openarray of any subtype.
You can enumerate on a loop index of your choice, it must be the first parameter.
Usage
import loopfusion
block: # Simplelet a =@[1, 2, 3]
let b =@[11, 12, 13]
let c =@[10, 10, 10]
forZip x in a, y in b, z in c:
echo (x + y) * z
# 120# 140# 160block: # With indexlet a =@[1, 2, 3]
let b =@[11, 12, 13]
let c =@[10, 10, 10]
var d: seq[int] =@[]
forZip i, x in a, y in b, z in c:
d.add i + x + y + z
doAssert d ==@[22, 25, 28]
block: # With mutationvar a =@[1, 2, 3]
let b =@[11, 12, 13]
let c =@[10, 10, 10]
forZip x invar a, y in b, z in c:
x += y * z
doAssert a ==@[111, 122, 133]
block: # With mutation, index and multiple statementsvar a =@[1, 2, 3]
let b =@[11, 12, 13]
let c =@[10, 10, 10]
forZip i, x invar a, y in b, z in c:
let tmp = i * (y - z)
x += tmp
doAssert a ==@[1, 4, 9]
block: # With iteration on seq of different typeslet a =@[1, 2, 3]
let b =@[false, true, true]
forZip integer in a, boolean in b:
if boolean:
echo integer
block: # With an expressionlet a =@[1, 2, 3]
let b =@[4, 5, 6]
let c = forZip(x in a, y in b):
x + y
doAssert c ==@[5, 7, 9]
block: # With arrays + seq, mutation, index and multiple statementsvar a = [1, 2, 3]
let b = [11, 12, 13]
let c =@[10, 10, 10]
forZip i, x invar a, y in b, z in c:
let tmp = i * (y - z)
x += tmp
doAssert a == [1, 4, 9]
Expressions must return value of the same types, i.e. you can't return void/no value at some iterations and a concrete value at other iterations.
Due to parsing limitations, expressions let foo = forZip(...) require parenthesis.
Name
The library name "Loop fusion" might be a bit confusing since there is no loop to fuse at start.
In spirit however, it is similar while "real" loop fusion merge multiple loops over multiple sequences.
Many would probably be curious why I first generate a zip iterator then a for-loop instead of for-looping directly.
This is because it started as a variadic zip proof of concept for Arraymancer for which I need an iterator to abstract iteration details, especially in the context of multithreading.
There should be no performance cost as Nim inlines iterators as if the loop was written manually.
About
Loop efficiently over a variadic number of containers