I'm trying to make a while loop that doesn't use any primitive loop blocks.
I tried this:
(condition is an unevaluated bool, and do is a C-Shaped command λ.)
I know that
works, but I can't seem to make it work in a custom block.
That worked! (though, it looks kinda ugly.) However, I thought that unevaluated didn't do anything different, besides not requiring a ring. (That's what it says in the manual.)
Oh. This surprised me, and then that surprised me; I can't believe this is the first time anyone's tried writing a recursive procedure with an unevaluated input.
The trouble is that the CONDITION input is still unevaluated when you make the recursive call:
The first screenshot shows the situation during the original call by the user. The second shows the situation during the recursive call. That's not what you want!
I'm embarrassed not to have a beautiful solution for this. The official right solution is to use a helper procedure:
I admit to not being completely sure myself of the differences between various unevaluated input types. I’m used to trying what works for a given purpose. I don’t know how to make “Boolean (unevaluated)” work here either. Perhaps Mr. Manual (@bh) could enlighten us.
Edit
… He already did (while I was writing the original version of this post). Even so, I’d prefer the Predicate solution.
Another edit
Meanwhile I found the following code to work, too (with “Boolean (unevaluated)”, and without a helper function!):
The trick is to use CALL (condition) as input for the recursive call.
Whatever floats your boat. The point of unevaluated inputs is to give your users tools whose implementation involves first class procedures, without the users having to know about first class procedures. Imagine you're implementing Scratch; your REPEAT UNTIL block is going to be a special form, with the two inputs unevaluated, whether or not there's something called "unevaluated" in the user-visible language. (For that matter, all C-shape input slots are unevaluated scripts, but Scratch users don't think of them as inputs at all.)
You’re right, of course. And with the solution as described in post 5 it can easily be implemented after all. Apparently the application of ‘“Boolean (unevaluated)” (as well as “Any (unevaluated”) is a non-trivial subject even for experienced Snap! users; iMAO it therefore deserves some more in-depth treatment in the Reference Manual.
The “wait 0 seconds” is there so it waits a frame before running it again, this prevents the “maximum call stack exeeded” error and makes it work like a normal scratch loop