please, somebody explain me this [zl queue] issue
I think there's something wrong with [zl queue].
Please check the example patch below.
I feed the queue with numbers 1 2 3 4 5 6 7 8 9.
and I have [select 3] after it that can bang back the [zl queue], so that when zl.queue outputs the number 3, the select bangs the queue again and SHOULD output even the next number (four), but it does instead output another number three (which triggers the select to output another bang to queue, etc etc
so when sending bangs to the queue, instead of this:
bang -> 1
bang -> 2
bang -> 3, 4
bang -> 5
...
bang -> 9
i'm getting
bang -> 1
bang -> 2
bang -> 3, 3, 3, 3, 3, 3, 3
PLEASE NOTE THAT I'M NOT LOOKING FOR A SOLUTION, BUT AN EXPLANATION.
I know this can be solved putting a [defer] between the output of [select 3] and input of [zl queue], but I would like to understand WHY it doesn't work without it. I haven't found any info about this issue in the ZL reference or help page and I have no idea when the [defer] is really needed. (would love to know when to use [defer] during coding, not during troubleshooting)
It's explained somehow in this article, see chapter 'Feedback Loops'.
broc: they write about stack overflow in the "feedback loops" section and i cannot see any stack overflow going on in my example patch.
BTW I didn't put the [print] on the right side and [select] on the left side. I did that so that the non-feedback part (print) is fed first, and only when all non-feedback stuff is done, then it gets back into another iteration of the loop. I thought it should be safe this way, but it somehow isn't
To me it seems like the outlets are holding their values until the bang (the one which made them output that value) is completely computed/over.
Which would mean that in this case, the zl queue output is holding the "3" value until processing of the third bang isn't completely over.
Perhaps, it would be better if the outlet would throwaway it's value when sending it to the last wire (which is the one which we could the use for feedbacks without hassle with defers and pipes)
Well it can be considered as a bug in the way zl.queue is written. I'll have a look at it.
In general something to realize with recursion is that you might still be inside the original object. so what is currently happening is that when select 3 is sending bang to zl.queue, the code in zl.queue which is after the outlet call hasn't been executed yet:
zl.queue code look like this:
outlet_int (right outlet)
outlet_somevalue (left outlet)
increment the index
the problem is that when the select object finds the value 3, it sends a bang which ask zl.queue to do that again:
bang->zl
zl's outlet_int
zl's outlet_somevalue
zl->print
zl->select (if that failed)
zl's increment the index
if the select succeed:
bang->zl
zl's outlet_int
zl's outlet_somevalue
zl->print
zl->select
zl's outlet_int
zl's outlet_somevalue
zl->print
zl->select
...
...
when there's no more things to output zl's outlet_int and zl's output_somevalue no longer output anything so it continues with dequeue what's next aka all the zl's increment index that didn't run (but you don't see this in the patcher, you only see that the index hasn't be incremented).
zl's increment the index
zl's increment the index
zl's increment the index
well not sure if that makes it any clearer though ;-)