That's good information, I suppose. Still doesn't let me chain iterators in a
"for" statement, leaving people having to examine my code to figure out what I
mean by "chain(a,b)" It also relies on magic identifiers like "str" and "v". I
ended up messing around with macros to get the desired behavior, which is
pretty silly, but here you go:
import macros
macro chaining(code: untyped): untyped =
const chainIdent = "chain"
const combineIdent = "combine"
proc inspect(depth: int, n: NimNode): NimNode =
case(n.kind)
of nnkIdent, nnkStrLit:
return n;
of nnkForStmt:
let onevar = n.len == 3
let call = n[n.len-2]
if call.kind == nnkCall:
proc get_iter(j: int): NimNode =
let item = call[j]
if item.kind == nnkIdent:
return newCall(item)
item
case($call[0].ident)
of chainIdent:
proc get_name(): NimNode =
if onevar:
return n[0]
result = newNimNode(nnkPar)
for i in 0..n.len - 2:
result.add(n[i])
let name = get_name()
let body = inspect(depth+1,n[n.len-1])
let list = newStmtList()
for j in 1..call.len-1:
list.add(newTree(nnkForStmt,name,get_iter(j),body.copy()))
# echo(treeRepr(list))
return newBlockStmt(list)
of combineIdent:
var body = inspect(depth+1,n[n.len-1])
var par = newNimNode(nnkPar)
for j in 1..call.len-1:
par.add(genSym(nskForVar))
var vars: NimNode
if onevar:
vars = newNimNode(nnkIdentDefs)
vars.add(n[0])
else:
vars = newNimNode(nnkVarTuple)
for i in 0..n.len - 3:
vars.add(n[i])
vars.add(newEmptyNode())
vars.add(par)
body.insert(0,newTree(nnkLetSection,vars))
for j in 1..call.len-1:
let iter = get_iter(j)
let sym = par[j-1]
let f = newTree(nnkForStmt,sym,iter,body)
body = f
# echo(treeRepr(body))
return body
else: discard
else: discard
var children: seq[NimNode] = @[]
for i in 0..n.len-1:
children.add(inspect(depth+1,n[i]))
result = newNimNode(n.kind)
if children.len > 0:
result.add(children)
result = inspect(0,code)
# echo(treeRepr(result))
iterator thing1: string =
yield "A"
yield "B"
yield "C"
iterator thing2: string =
yield "D"
yield "E"
yield "F"
yield "cookiemonster"
iterator thing3(i: int): int =
yield 1+i
yield 2+i
yield 3+i
chaining:
echo("regular iteration.......")
for thing in thing1():
echo(thing)
echo("chaining.......")
for thing in chain(thing1,thing2,["wait, try that
again"],thing1,thing3(0),"derp"):
echo(thing)
echo("combinations.......")
for a,b in combine(thing1,thing3(39)):
echo(a, " ", b)
echo(".......")
for a,b in combine(thing1,thing1):
echo(a, " ", b)
echo("can capture as a tuple-ish thing.......")
for thing in combine(thing1,thing3(23)):
echo(thing)
let (a,b) = thing
echo(a," ",b)