Elegant way for do ... while in groovy - loops

How to do code something like this in groovy?
do {
x.doIt()
} while (!x.isFinished())
Because there is no do ... while syntax in groovy.
No 'do ... while()' syntax as yet.
Due to ambiguity, we've not yet added support for do .. while to Groovy
References:
groovy - dev > do while
Migration From Classic to JSR syntax
Groovy Documentation > Control Structures > Looping
Rosetta Code > Loops/Do-while Groovy

You can roll your own looping that's almost what you want.
Here's an example with loop { code } until { condition }
You can't have a corresponding loop { code } while { condition } because while is a keyword.
But you could call it something else.
Anyway here's some rough and ready code for loop until.
One gotcha is you need to use braces for the until condition to make it a closure.
There may well be other issues with it.
class Looper {
private Closure code
static Looper loop( Closure code ) {
new Looper(code:code)
}
void until( Closure test ) {
code()
while (!test()) {
code()
}
}
}
Usage:
import static Looper.*
int i = 0
loop {
println("Looping : " + i)
i += 1
} until { i == 5 }

So many answers and not a single one without a redundant call, a shame ;)
This is the closest it can get to purely language syntax based do-while in Groovy:
while ({
x.doIt()
!x.isFinished()
}()) continue
The last statement within curly braces (within closure) is evaluated as a loop exit condition.
Instead of continue keyword a semicolon can be used.
Additional nice thing about it, loop can be parametrized (kind of), like:
Closure<Boolean> somethingToDo = { foo ->
foo.doIt()
!foo.isFinished()
}
and then elsewhere:
while (somethingToDo(x)) continue
Formerly I've proposed this answer over here: How do I iterate over all bytes in an inputStream using Groovy, given that it lacks a do-while statement?

Depending on your use case, there are options like this: do .. while() in Groovy with inputStream?
Or you can do:
x.doIt()
while( !x.finished ) { x.doIt() }
Or
while( true ) {
x.doIt()
if( x.finished ) break
}

You can use a condition variable with the regular while loop:
def keepGoing = true
while( keepGoing ){
doSomething()
keepGoing = ... // evaluate the loop condition here
}

Update Groovy 2.6 has been abandoned to concentrate on 3.0.
From Groovy 2.6 on, do-while is supported when enabling the new Parrot Parser, from Groovy 3.0 on this is the default. See release notes:
// classic Java-style do..while loop
def count = 5
def fact = 1
do {
fact *= count--
} while(count > 1)
assert fact == 120

By now, Groovy has support for do/while:
do {
x.doIt()
} while (!x.isFinished())

Or you can implement it in a Groovier way :
def loop(Closure g){
def valueHolder = [:]
g.delegate = valueHolder
g.resolveStrategy = Closure.DELEGATE_FIRST
g()
[until:{Closure w ->
w.delegate = valueHolder
w.resolveStrategy = Closure.DELEGATE_FIRST
while(!w()){
g()
}
}]
}

Related

Would like to stop execution of code when a match is met

I created this service method in Angular JS which checks if an array of potential statuses(pendingApplications) match any of an array of set statuses(applicableStatuses). For this to work it meetsStatusCondition should return true after the first match occurs. Only 1 of the numbers in pendingApplications array needs to match and I'd like to end the execution of this function. Currently it's looping through every item in pendingApplications array
`containsApplicableStatus: function(pendingApplications, applicableStatuses) {
pendingApplications.forEach(function(status) {
if (applicableStatuses.includes(status)) {
return pendingApplications.meetsStatusCondition = true;
}
});
}`
This is a limitation with .forEach, you can't break out if it like you can with a for loop
Just a regular for loop will work
for (const status of applicableStatuses){
if (applicableStatuses.includes(status)) {
pendingApplications.meetsStatusCondition = true;
break //or return if you want to exit out of the enclosing function instead of just the loop
}
}
Often when you want to short-circuit a forEach like this, what you're really looking for is another method like find() or some().
containsApplicableStatus: function(pendingApplications, applicableStatuses) {
pendingApplications.meetsStatusCondition = pendingApplications.some(function(status) {
return applicableStatuses.includes(status)
});
}
There is no point in using forEach (which doesn't have a breaking option) if you could just use a regular for ... of loop instead:
containsApplicableStatus: function(pendingApplications, applicableStatuses) {
for (const status of pendingApplications) {
if (applicableStatuses.includes(status)) {
pendingApplications.meetsStatusCondition = true;
break;
}
}
}
However, even this seems a bit too complicated, you could just set meetsStatusCondition to the result of some:
containsApplicableStatus: function(pendingApplications, applicableStatuses) {
pendingApplications.meetsStatusCondition =
pendingApplications.some(status => applicableStatues.includes(status));
}
I do wonder if it makes sense to set a non-index property on your array though, maybe rethink that. This works but it's usually not something you'd expect on an array, and it will be lost if you convert that array to JSON for instance.

Jump out of for loop in kotlin

I have this simple loop and condition, but you see below I can't jump out of loop :
rwloop# for (z in rendered_words.size-1 downTo 0 )
{
var css_=rendered_words[z].node.attr("class")
css_?.let {
if (css_=="classzero") {
break#rwloop
}
}
}
But I receive this error in break#rwloop :
break' or 'continue' jumps across a function or a
class boundary
Drop the let lambda since the #rwloop label is not visible inside it and use this:
rwloop# for (z in rendered_words.size-1 downTo 0 )
{
var css_=rendered_words[z].node.attr("class")
if (css_ != null) {
if (css_=="classzero") {
break#rwloop
}
}
}
https://kotlinlang.org/docs/reference/inline-functions.html#non-local-returns
It states that
break and continue are not yet available in inlined lambdas, but we are planning to support them too.
So, you should
Wait until its support comes
Or use local return statement instead,
How?
The lambda is a function itself, so you can return from it, this (if it is the last thing in the for loop like your case) will make the same effect of continue
rwloop# for(z in rendered_words.size-1 downTo 0 ) {
var css_=rendered_words[z].node.attr("class")
css_?.let {
if (css_=="classzero") {
return#let
}
}
}
Kotlin considers the lambda as a boundary (it is not an inner class because it is inlined), so you can't cross it by break nor continue till now.

How to stop executing a loop (say if loop once it finds a match) in Protractor for AngularJS applications?

I am writing test cases using protractor for AngularJS Application. I want to stop an if loop once it finds the value. Is there any equivalent function available that I can use to stop executing the loop further in Protractor, like we have break in C.
break is a javascript instruction:
function testBreak(x) {
var i = 0;
while (i < 6) {
if (i == 3) {
break;
}
i += 1;
}
return i * x;
}
A complete reference of the language is available on the mozilla developer network with a list of all the statements.
Brendan Eich wrote:
JavaScript borrows most of its syntax from Java, but also inherits
from Awk and Perl, with some indirect influence from Self in its
object prototype system.
NB: This question is neither specific to protractor, nor angular.js nor to automation.
you also have the break statement in javascript.
There is break/continue in javascript:
http://www.w3schools.com/js/js_break.asp
This is my code and i want break after if statement because text has been match i dont want to again go to else block
for (i = 0; i <row.length; i++)
{
var obj_dn_ocnele=obj_dn_ocndrpdown_elements.get(i).getText().then(function(text) {
var test_var1 = text.trim();
console.log(test_var1);
outer:{
if (test_var1 == var_ocn_id)
{
log.info(var_ocn_id +"ocn exist");
break outer;
}
else
{
log.error(var_ocn_id +"ocn not exist");
break outer;
}
}
});
}

Array.tabulate StackOverFlowError

I'm new to Scala and I was playing around with the Array.tabulate method. I am getting a StackOverFlowError when executing this simplified piece of code snippet (originally a dp problem).
import Lazy._
class Lazy[A](x: => A) {
lazy val value = x
}
object Lazy {
def apply[A](x: => A) = new Lazy(x)
implicit def fromLazy[A](z: Lazy[A]): A = z.value
implicit def toLazy[A](x: => A): Lazy[A] = Lazy(x)
}
def tabulatePlay(): Int = {
lazy val arr: Array[Array[Lazy[Int]]] = Array.tabulate(10, 10) { (i, j) =>
if (i == 0 && j == 0)
0 // some number
else
arr(0)(0)
}
arr(0)(0)
}
Debugging, I noticed that since arr is lazy and when it reaches the arr(0)(0) expression it tries to evaluate it by calling the Array.tabulate method again -- infinitely over and over.
What am i doing wrong? (I updated the code snippet since I was basing it off the solution given in Dynamic programming in the functional paradigm in particular Antal S-Z's answer )
You have effectively caused an infinite recursion. You simply can't reference a lazy val from within its own initialization code. You need to compute arr(0)(0) separately.
I'm not sure why you are trying to access arr before it's built, tabulate seems to be used to fill the array with a function - calling arr would always result in infinite recursion.
See Rex's example here (and a vote for him), perhaps that will help.
In a multidimensional sequence created with tabulate, is the innermost seq the 1. dimension?
I was able to solve this by wrapping arr(0)(0) in Lazy so it is evaluated as a call-by-name parameter, thereby not evaluating arr in the tabulate method. The code that I referenced was automatically converting it using implicits (the binary + operator), so it wasn't clear cut.
def tabulatePlay(): Int = {
lazy val arr: Array[Array[Lazy[Int]]] = Array.tabulate(10, 10) { (i, j) =>
if (i == 0 && j == 0)
1 // some number
else
new Lazy(arr(0)(0))
}
arr(0)(0)
}
Thanks all.

Loops' iterating in ANTLR

I'm trying to make a Pascal interpreter using ANTLR and currently have some troubles with processing loops while walking the AST tree.
For example for loop is parsed as:
parametricLoop
: FOR IDENTIFIER ASSIGN start = integerExpression TO end = integerExpression DO
statement
-> ^( PARAMETRIC_LOOP IDENTIFIER $start $end statement )
;
(variant with DOWNTO is ignored).
In what way can I make walker to repeat the loop's execution so much times as needed? I know that I should use input.Mark() and input.Rewind() for that. But exactly where should they be put? My current wrong variant looks so (target language is C#):
parametricLoop
:
^(
PARAMETRIC_LOOP
IDENTIFIER
start = integerExpression
{
Variable parameter = Members.variable($IDENTIFIER.text);
parameter.value = $start.result;
}
end = integerExpression
{
int end_value = $end.result;
if ((int)parameter.value > end_value) goto EndLoop;
parametric_loop_start = input.Mark();
}
statement
{
parameter.value = (int)parameter.value + 1;
if ((int)parameter.value <= end_value)
input.Rewind(parametric_loop_start);
)
{
EndLoop: ;
}
;
(Hope everything is understandable). The condition of repeating should be checked before the statement's first execution.
I tried to play with placing Mark and Rewind in different code blocks including #init and #after, and even put trailing goto to loops head, but each time loop either iterated one time or threw exceptions like Unexpected token met, for example ':=' (assignement). I have no idea, how to make that work properly and can't find any working example. Can anybody suggest a solution of this problem?
I haven't used ANTLR, but it seems to me that you are trying to execute the program while you're parsing it, but that's not really what parsers are designed for (simple arithmetic expressions can be executed during parsing, but as you have discovered, loops are problematic). I strongly suggest that you use the parsing only to construct the AST. So the parser code for parametricLoop should only construct a tree node that represents the loop, with child nodes representing the variables, conditions and body. Afterwards, in a separate, regular C# class (to which you provide the AST generated by the parser), you execute the code by traversing the tree in some manner, and then you have complete freedom to jump back and forth between the nodes in order to simulate the loop execution.
I work with ANTLR 3.4 and I found a solution which works with Class CommonTreeNodeStream.
Basically I splitted off new instances of my tree parser, which in turn analyzed all subtrees. My sample code defines a while-loop:
tree grammar Interpreter;
...
#members
{
...
private Interpreter (CommonTree node, Map<String, Integer> symbolTable)
{
this (new CommonTreeNodeStream (node));
...
}
...
}
...
stmt : ...
| ^(WHILE c=. s1=.) // ^(WHILE cond stmt)
{
for (;;)
{
Interpreter condition = new Interpreter (c, this.symbolTable);
boolean result = condition.cond ();
if (! result)
break;
Interpreter statement = new Interpreter (s1, this.symbolTable);
statement.stmt ();
}
}
...
cond returns [boolean result]
: ^(LT e1=expr e2=expr) {$result = ($e1.value < $e2.value);}
| ...
Just solved a similar problem, several points:
Seems you need to use BufferedTreeNodeStream instead of CommonTreeNodeStream, CommonTreeNodeStream never works for me (struggled long time to find out)
Use seek seems to be more clear to me
Here's my code for a list command, pretty sure yours can be easily changed to this style:
list returns [Object r]
: ^(LIST ID
{int e_index = input.Index;}
exp=.
{int s_index = input.Index;}
statements=.
)
{
int next = input.Index;
input.Seek(e_index);
object list = expression();
foreach(object o in (IEnumerable<object>)list)
{
model[$ID.Text] = o;
input.Seek(s_index);
$r += optional_block().ToString();
}
input.Seek(next);
}

Resources