{"issue":{"state":"open","pull_request":{"diff_url":null,"html_url":null,"patch_url":null},"milestone":null,"user":{"avatar_url":"https://secure.gravatar.com/avatar/d85f004f2e159efa917f2e394598fbff?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","gravatar_id":"d85f004f2e159efa917f2e394598fbff","url":"https://api.github.com/users/pangloss","login":"pangloss","id":10115},"labels":[],"assignee":null,"updated_at":"2011-10-31T20:05:03Z","comments":0,"closed_at":null,"url":"https://api.github.com/repos/pangloss/pacer/issues/8","body":"Because pipe instances sometimes are stateful, their behaviour within a data loop can be difficult to predict and counterintuitive. For instance, the range filter:\r\n\r\n```ruby\r\ngraph.v.loop { |v| v.out[0] }.while { :loop_and_emit }\r\n```\r\n\r\nIt would make sense for this loop to be equivalent to:\r\n\r\n```ruby\r\ngraph.v.out[0] + graph.v.out[0].out[0] + graph.v.out[0].out[0].out[0] + ... \r\n```\r\n\r\nbut in fact it is equivalent to:\r\n\r\n```ruby\r\ngraph.v.out[0]\r\n```\r\n\r\nbecause the range filter is not reset on each loop. The elements that are looped are mixed with the starting elements and fed back through the same `out[0]` pipe fragment which allows only the first element through and then stops emitting.\r\n\r\nAnother problem with this approach is that the order of iteration is uncontrollable because all emitted elements are mixed together in one queue that competes with the elements that are initially fed into the loop.\r\n\r\nInstead of that it would make more sense to dynamically generate a pipe fragment for each depth of recursion within the loop, so the same definition would produce numerous `out[0]` pipes, each with their own queue that can be iterated in either depth-first or breadth first order.\r\n\r\nBecause the block generating the pipe fragment would be called once for each depth, it seems sensible to feed that block some context such as its current depth and the previous pipeline fragments. That would also make it possible to do things like aggregation, something like these bits of pseudo code:\r\n\r\n```ruby\r\ngraph.v.\r\n  loop { |v, context| v.out.aggregate(context.first? ? LinkedList.new : context.prev.pipe.getSideEffect) }.\r\n  while { :emit_and_loop }.\r\n  cap\r\n\r\ngraph.v.\r\n  loop do |v, context|\r\n    context.data = LinkedList.new\r\n    if context.first?\r\n      v.out.aggregate(context.data)\r\n    else\r\n      v.out.except(context.prev.data).aggregate(context.data)\r\n    end\r\n  end.\r\n  while { |element, path, context| context.data.length < 10 }\r\n\r\ngraph.v.loop { |v, context| v.out.limit(context.depth * 2) }.while { true }\r\n````\r\n\r\n","html_url":"https://github.com/pangloss/pacer/issues/8","number":8,"title":"Make the loop pipe actually build a chain internally","id":2101536,"created_at":"2011-10-31T20:05:03Z"},"action":"opened"}