foreach without front

H. S. Teoh via Digitalmars-d digitalmars-d at puremagic.com
Thu Aug 14 11:22:04 PDT 2014


On Thu, Aug 14, 2014 at 10:39:48AM -0700, Ali Çehreli via Digitalmars-d wrote:
[...]
> The syntax does not allow that but I have discovered a WAT! :) If you
> implement iteration by opApply() member functions, it is possible to
> use any random name and it works.
> 
> The following type provides both an int and a void overload.
> 
> import std.stdio;
> 
> struct S
> {
>     int opApply(int delegate(int) dg)
>     {
>         foreach (i; 0 .. 3) {
>             int b = dg(i);
>             if (b) {
>                 return b;
>             }
>         }
> 
>         return 0;
>     }
> 
>     int opApply(int delegate() dg)
>     {
>         foreach (_; 0 .. 3) {
>             int b = dg();
>             if (b) {
>                 return b;
>             }
>         }
> 
>         return 0;
>     }
> }
> 
> void main()
> {
>     auto s = S();
>     foreach (i; s) {
>         writeln(i);
>     }
> 
>     // Replace WAT with any other random name and it still works.
>     // foreach (_; s) would make the most sense.
>     foreach (WAT; s) {
>         writeln("_");
>     }
> }
[...]

This is not a WAT.  The above code only calls the first overload of
opApply. It's not a WAT to allow any random name -- since it's up to the
user to choose the name of the iteration variable. If you print out the
type and value of 'WAT', you'll see that it takes on the values passed
in by the first overload of opApply (to disambiguate this from the
built-in indexing, change the foreach loop in the first opApply to, say,
17..21, and look at the values of 'WAT').

It's actually not possible to call the second overload of opApply from
within a foreach; I tried this:

	struct S {
		int opApply(scope int delegate() dg) {
			foreach (_; 0..3) {
				auto rc = dg();
				if (rc) return rc;
			}
			return 0;
		}
	}
	void main() {
		S s;
		foreach (_; s) {
		}
	}

and the compiler said:

	test.d(12): Error: cannot infer argument types, expected 0 argument, not 1

But if I delete the loop variable '_' (i.e., foreach (; s)), the
compiler says:

	test.d(12): Error: basic type expected, not ;
	test.d(12): Error: no identifier for declarator int

Deleting the ';' (i.e., foreach (s)) leads to:

	test.d(12): Error: no identifier for declarator s
	test.d(12): Error: found ')' when expecting ';'
	test.d(14): Error: found '}' when expecting ')'
	test.d(15): Error: found 'EOF' instead of statement
	test.d(15): Error: found 'EOF' when expecting '}' following compound statement

So basically, it's impossible to invoke an opApply that takes an
argumentless delegate from a foreach.


T

-- 
My program has no bugs! Only undocumented features...


More information about the Digitalmars-d mailing list