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)
    

Reply via email to