Open GlaireDaggers opened 3 years ago
I agree with the 'do { ... } while(...)' addition.
Though, I found the do { ... }
block a little bit confusing mostly because you have to reach the end of the block to see if there is or not a while statement, thought I agree it can be a nice complement when editing code live. In addition, when I read it first (before I had to trash my original response), I thought it would be about a forever
loop which would have been a great addition, but maybe it is only my expectations.
That is an interesting point about having to scan to the end of the block to see its behavior, but I suppose that's already true of a do..while anyway (you have to find the end of the block to see what its continue condition is).
I think it's also a good point about what the behavior of a do block without a while condition should be. The way I originally wrote it, it was a do..while construct without a continue condition - that is, without the continue check, it would simply emit code to "fall through" out of the loop. But should it instead be a loop that, in the absence of a continue condition, simply loops back to the top unconditionally? I figured that having some kind of construct that was a breakable one-off block of code would be useful - while you could certainly emulate that with a do..while(false) or just inserting a break, there's a small possibility that allowing an omitted while statement to become an infinite loop could turn into a footgun of sorts (accidentally writing code that doesn't loop would be in most cases less disastrous than accidentally writing code that loops forever). Would love to get more feedback on this though.
Well block is already supported. So the question is do we want to have do
blocks as an error like other languages, a glorified block to ease live
coding, or something else of some meaning, incidentally forever
block as
some interesting meaning. Every solutions have their pro and cons, and I'm
fine with any final decisions.
I don't want to push for the forever
loop in that particular form, but
because of the simplicity of the compiler, it would also be nice to have
that feature in the language somehow, and not waste some time because the
compiler can't optimise true/false constant to allow direct branching.
I'd certainly support the addition of continue
and do {..} while
to the language. Anyone who's programmed in the industry C-family languages (C, C++, C#, Java etc) just expects these constructs to be there and it can be tiresome to program around their absence.
However, I'm not so sure about do {..}
for two reasons:
Firstly, I think it's potentially confusing. When I was reading your opening post then, like @mhermier, I was expecting it to represent an infinite loop rather than a once (at most) loop.
I'm not sure that it's important enough to have its own construct as, if we had do {...} while
, it could be simulated with do {..} while (false)
.
As far as an infinite loop is concerned, I think there's a case for adding one which is shorter to type than while (true)
though my own preference would be a for
loop with an empty range i.e. for() {..}
. That would mirror more closely the for (;;) {..}
construct which the above mentioned languages often use for such a loop.
I don't think we need do...while
but a continue
would be highly appreciated, to complement the break
statement.
Although I'd personally like to see do...while
, I agree that continue
is the most important of the three proposals.
Didn't think of it, but to sum up what new features I would like to see:
for() {...}
forever loopdo {...} while(...)
because sometimes it express better than regular
while loopcontinue
for all existing loops, because it is useful.I think it looks like the safest route to go with a PR is:
do..while
, but remove the ability to omit the while clause - one-off blocks can simply be emulated with a false condition. forever blocks would be a different construct, and could continue to be discussed & possibly implemented in a separate PRcontinue
Sounds good to me :)
I would love to have a continue
to complement break
, and do-while
loops.
This is up to @ruby0x1, of course, but for what it's worth, I would be happy to see continue
and do-while
in Wren. I don't think do { ... }
for an infinite loop quite carries its weight, especially given the potential confusion.
I'll have a closer look soon, but the only one I feel inclined toward and have missed countless times over the years is continue
.
Wren just isn't the language with all the features, so adding too many ways to do the same thing at the cost of complexity isn't what I see happening.
Fair. There's a really good case to be made for trying to keep things simple. While I do think do..while has merit in that I don't simply consider it another way to do loops (its behavior is notably different, and that difference can in several scenarios be quite helpful), I also agree that between those continue
is the most important addition.
The difference between do while and while is that the one executes at least once right? So what I mean is you do have the tools to do that with the language already, it's a specific specialization of while, not a different kind of loop.
i.e these are equivalent, except condition
is read once vs twice.
The use of break
+ conditions being set + functions are all valid tools in this context too.
var condition = true
do {
System.print("once")
condition = false
} while(condition)
var condition = true
while(condition) {
System.print("once")
condition = false
}
@ruby0x1 these are fundamental blocks, they exist to simplify readability and ease execution flow understanding. They are not that expensive since the loop infrastructure is already in place, and avoid bloated code.
@ruby0x1 Yeah, and to be fair I suppose any do..while can be (mostly) emulated as a while with a break condition, albeit with an extra compare.
I think I will move ahead with pruning do..while from my branch and just raising a PR for continue
. That by itself will already be quite useful.
Opening an issue to propose adding do, do..while, & continue constructs to Wren. I have a fork which implements these & adds new test cases for them already, but wanted to open a discussion about their syntax & make sure it fits with others' idea of what Wren should be.
The features are of course very simple: a new
continue
statement which, in any loop (for, while, or do..while), will jump to the iterator or condition check for the next loop iteration. Example:Can be used to skip the remainder of a particular iteration of a loop early. In the current main branch of Wren this can be done with if statements, but continue would overall reduce the verbosity of such constructs.
The other new feature would be a new loop: do..while. This acts precisely like do..while in most other languages. It's similar to a while, but the evaluation of the condition is deferred until after the loop body.
This can be handy in cases where the body of the loop sets up the condition to continue the loop, but you need to guarantee that the body is executed at least once first. For example:
The same scenario could be accomplished in the current main branch of Wren by duplicating the loop body, but do..while would reduce code duplication in that case:
Additionally, in my fork, the do..while statement can also have its while condition omitted. This creates what is functionally equivalent to a do..while(false):
The benefit of this is a block of code which can be broken out of early:
This one seems like it might be less important, but as it was not terribly difficult to add and could still be useful I decided to include it anyway.