dlang.org icon indicating copy to clipboard operation
dlang.org copied to clipboard

[Statements] "foreach over delegates" has suspicious nested delegate with return 0

Open crazymonkyyy opened this issue 2 months ago • 2 comments

I know if return 0 is bug prone as return 1 and havnt looked for an example of it breaking labeled break, but......

foreach (x; &myLoop) that & is nesting a delegate of delegates; which suggests when this code was written is was someone searching for something that "just werked" (probably copy and pasted from an opApply code example ) rather than the simplest/idiomatic pattern of what the feature can do.

code im currently playing with:

#!opend test app
import std;
auto toiter(R)(ref R r) if (isInputRange!R){
	return (int delegate(ref ElementType!R) dg){
		int ret;
		while( ! r.empty){
			ret=dg(r.front);
			r.popFront;
			if(ret){return ret;}
		}
		return ret;
	};
}
auto toiter(T)(ref T t) if ( ! isInputRange!T){
	return (int delegate(ref T) dg){
		return dg(t);
	};
}
unittest{
	auto foo=iota(9).toiter;
	foo=10.toiter;
	auto bar=iota(9).toiter;
	excape:foreach(i;foo){
		foreach(j;bar){
			writeln(i,',',j);
			if(j==10){ break excape;}
	}}
	"---".writeln;
	foo=iota(9).toiter;
	bar=10.toiter;
	excape2:foreach(i;foo){
		foreach(j;bar){
			writeln(i,',',j);
			if(j==10 && i==2){ break excape2;}
	}}
}

crazymonkyyy avatar Sep 24 '25 21:09 crazymonkyyy

I know if return 0 is bug prone as return 1

return 0 is fine iff none of the delegate calls returned non-zero.

foreach (x; &myLoop) that & is nesting a delegate of delegates

I don't see what's wrong with that. How would you make the example simpler?

ntrel avatar Sep 25 '25 19:09 ntrel

// Custom loop implementation, that iterates over powers of 2 with
// alternating sign. The foreach loop body is passed in dg.
auto myLoop(int until) => (int delegate(ref int) dg){
	int result;
	int a=1;
	while(a<until){
		result = dg(a);
		a*=-2;
		// If the loop body contains a break, ret will be non-zero.
		if (result != 0)
			return result;
	}
	 return result;
};

// Append each value in the iteration to an array
unittest{
	int[] result;
	foreach (x; myLoop(128))
	{
		result ~= x;
	}
	assert(result == [1, -2, 4, -8, 16, -32, 64, -128]);
}

crazymonkyyy avatar Sep 26 '25 18:09 crazymonkyyy