Upvars not updated outside the defining block

Hi everyone,

I am trying to implement a "for item in stream str do action while pred" block, however, the item (as an upvars) not being updated in the action block, but during the testing inside the implementation it's captured properly. I am wondering if there is something I need to do specifically do make sure that item can be passed back during the action block execution.

Here is the implementation:
for item in stream do action while predict

I tried both run action with or without continuation, but it does not make a difference.

test case for item in stream do action while predict

You can see that item was flashed three times, but each time it's showing 1, if I put the same say item command in the implementation itself, it correctly displays 1, 2, 3.

Thanks in advance for any help.

Upvars do not work with recursion. This is because variables keep their context. In this case, you create a variable outside the block, but then the second loop creates a new variable in the block, in the second loop, and so on. To fix this, just don't use recursion.

Thank @ego,

Got it. I will work out a fix.

... and don't use RUN W/CONTINUATION.

Thanks @bh for your advice.

I have made the change, I need to exit the loop with a breakout, I used an ugly approach, is there a more elegant approach?

for item in stream do action while pred version 2

Oh, in that case I guess you should do


but I'm tempted to say that if you have a loop with three end tests (running out of stream, PRED, and BREAKOUT) there must be a simpler way to accomplish whatever it is you're trying to do.

Thanks @bh,

I tried your suggestion, but it did not breakout, I don't really understand this code block. Could you please explain to me a little bit more so I could understand?

Here is the version I am incorporating your code:

for item in stream do action while pred version 3

The following works, however, as you can see, head of stream was used twice, I want to see whether I can use head of stream only once.

for item in stream do action while pred version 2

Oh. Try this:


It's the ELSE part that's new. This is what you want, right? If PRED fails, stop the entire loop, not just this stream element.

And seeing this, I also have to clarify what running BREAKOUT should do. Should it, too, stop the entire loop? If so, my code is wrong; it has to be


so that the entire loop is part of the code whose continuation you're grabbing.

Finally, is there a reason for the variable CURRENT STR as opposed to just using STR throughout? Because the way you have it, the program keeps a pointer to the very beginning of the stream, so stream memory can't be reclaimed as you process each element. So I would do

Thanks @bh for your code.

Yes, I did want to stop the entire loop, however, I would like any code after the calling block still to be executed.

In the past, I tested both Stop this block and Stop this script, it had problems, especially it would not execute any more code after the customized for loop.

For example:

code blocks
**for item in stream str do **
action
while pred
code block after... (<==== won't execute)

I will do some more testing to confirm.

However, I did improve my version 2 using the repeat while loop, this is built on the assumption that for AND predict block would only proceed to test the second part if the first part is true (as if it's false, there is no need to evaluate the second predict).

for item in stream do action while pred version 2 improved

I am still interested in learning how to use the run with continuation, it seems to me the best usage (as it described in your amazing manual) is to optimize the loop when certain condition meet to avoid further looping, this is best in situations when we want to find the first one matching certain condition, which is exact in our case.

Thanks a lot.

Hi @bh,

Just tested your code, it's working perfect, does the run with continuation provide the code below the for loop to continue the execution? I used stop this block without the run with continuation before, and the code won't run below it.

Yes, RUN W/CONTINUATION (hereafter RUN/CC) sets the continuation to be whatever is left to do in the script once the stuff inside the RUN/CC finishes. So RUN (BREAKOUT) (plain old run, not RUN/CC) will jump out to whatever comes after the RUN/CC, which in this case is just what's left to do in the caller of this block.

In my previous version, the RUN/CC just included a single time doing RUN (ACTION) so RUN (BREAKOUT) would just continue with the next item in the stream. Instead you want the entire input to WARP to be inside the RUN/CC.

STOP THIS SCRIPT stops the toplevel script, ending any pending procedure calls. You have to use STOP THIS BLOCK, which should stop the FOR block.