Thread overview
foreach UFCS
Mar 31, 2016
ixid
Mar 31, 2016
Rene Zwanenburg
Mar 31, 2016
Adam D. Ruppe
Mar 31, 2016
ixid
Mar 31, 2016
Q. Schroll
March 31, 2016
What is going on with UFCS and foreach?

foreach(i;0..5).writeln;

This prints five line breaks.

foreach(i;0..5).i.writeln;

This will not compile.

foreach(i;0..5).writeln(i);

This writes out 1 to 4 on separate lines. Is this supposed to work? I thought a.b would be rewritten to b(a) with UFCS but writeln(foreach(i;0..5)) is nonsensical and does not compile and should be the same as foreach(i;0..5).writeln;
March 31, 2016
On Thursday, 31 March 2016 at 13:39:25 UTC, ixid wrote:
> What is going on with UFCS and foreach?
>
> foreach(i;0..5).writeln;
>
> This prints five line breaks.
>
> foreach(i;0..5).i.writeln;
>
> This will not compile.
>
> foreach(i;0..5).writeln(i);
>
> This writes out 1 to 4 on separate lines. Is this supposed to work? I thought a.b would be rewritten to b(a) with UFCS but writeln(foreach(i;0..5)) is nonsensical and does not compile and should be the same as foreach(i;0..5).writeln;

The compiler interprets it as a foreach without curly braces. With curlies it would look like:
foreach(i; 0..5)
{
  .writeln();
}

In this context the dot means the writeln lookup should happen from the module level scope.
March 31, 2016
On Thursday, 31 March 2016 at 13:39:25 UTC, ixid wrote:
> What is going on with UFCS and foreach?

There's no such thing as UFCS on foreach. UFCS only works on variables, not a foreach statement.

> foreach(i;0..5).writeln;

You can add a line break and optional braces there to see what it really is:

foreach(i;0..5) {
   .writeln;
}


It is just an ordinary loop calling writeln 5 times. The leading dot in D means "look up in the global namespace".

> foreach(i;0..5).i.writeln;

foreach(i; 0 .. 5) {
   .i.writeln;
}

It is trying to look up a name i in global scope, and calling writeln on it.

This is why the .name syntax exists: so you can bypass local variables with the same name when trying to access a global.

It would compile if you put an `int i;` at the top of your module... try it!


> foreach(i;0..5).writeln(i);

foreach(i; 0 .. 5) {
   .writeln(i); // leading . just means call global writeln
}




What you're seeing is similar to the Java hoax where people say it supports hyperlinking:

public static void main() {
   http://dlang.org/awesome
}


That compiles, but it isn't a link, it just looks like one at first.

It is actually a label, "http:", followed by a comment, "//dlang.org....". Two legal things without whitespace that looks like something else at first glance.
March 31, 2016
On Thursday, 31 March 2016 at 13:39:25 UTC, ixid wrote:
> What is going on with UFCS and foreach?
>
> foreach(i;0..5).writeln;

This is not UFCS; it is calling writeln on module scope. See http://dlang.org/spec/module.html#module_scope_operators

Your code is semantically identical with

foreach (i; 0 .. 5)
{
    .writeln; // module scope operator!
}

Furthermre because there is no local variable writeln that could be confused with the imported function, the code is identical with

foreach (i; 0 .. 5)
{
    writeln;
}

> This prints five line breaks.
>
> foreach(i;0..5).i.writeln;
>
> This will not compile.

It does not compile because i is not an identifier at module scope. i is a local variable and a hypothetical i at module scope (accessible via .i) is not declared, therefore this is an error.

> foreach(i;0..5).writeln(i);
>
> This writes out 1 to 4 on separate lines. Is this supposed to work? I thought a.b would be rewritten to b(a) with UFCS but writeln(foreach(i;0..5)) is nonsensical and does not compile and should be the same as foreach(i;0..5).writeln;

It does rewrite. But only if there is an expression beforehand the dot. Here it just isn't. The "foreach (i; 0 .. 5)" is not a complete expression.
March 31, 2016
On Thursday, 31 March 2016 at 13:48:27 UTC, Adam D. Ruppe wrote:
> It is trying to look up a name i in global scope, and calling writeln on it.
>
> This is why the .name syntax exists: so you can bypass local variables with the same name when trying to access a global.
>
> It would compile if you put an `int i;` at the top of your module... try it!


Thanks, that makes sense! I had forgotten the global dot syntax. That seems like a somewhat sketchy syntax given how little one would use it, wouldn't something like:

writeln(i).global;

be much clearer for globals?