Thread overview
stdio.lines doesn't have popFront, but works with foreach
Dec 11, 2014
Andrew Klaassen
Dec 11, 2014
bearophile
Dec 11, 2014
Andrew Klaassen
Dec 11, 2014
Kapps
Dec 11, 2014
Andrew Klaassen
December 11, 2014
The docs for stdio.lines say that it's a struct.  stdio.lines works with foreach.

The docs for foreach say:

"Iteration over struct and class objects can be done with ranges. For foreach, this means the following properties and methods must be defined: .empty ... .front ... .popFront()"

But when I try to access any of those properties or methods for stdio.lines, I get compilation errors:

  1 import io = std.stdio;
  2
  3 void main(string[] args) {
  4
  5     auto infile = io.File(args[1], "r");
  6
  7     auto filelines = io.lines(infile);
  8
  9     io.writeln(filelines.front);
 10     io.writeln(filelines.empty);
 11     io.writeln(filelines.popFront());
 12 }

test_filechunking.d(9): Error: no property 'front' for type 'lines'
test_filechunking.d(10): Error: no property 'empty' for type 'lines'
test_filechunking.d(11): Error: no property 'popFront' for type 'lines'

Why is this?

I'm using ldc2 for compilation, FWIW.

Andrew

December 11, 2014
Andrew Klaassen:

> The docs for stdio.lines say that it's a struct.  stdio.lines works with foreach.

If you want a range use "myfile".File.byLine or "myfile".File.byLineCopy.

Bye,
bearophile
December 11, 2014
On Thursday, 11 December 2014 at 20:17:50 UTC, bearophile wrote:
> Andrew Klaassen:
>
>> The docs for stdio.lines say that it's a struct.  stdio.lines works with foreach.
>
> If you want a range use "myfile".File.byLine or "myfile".File.byLineCopy.
>
> Bye,
> bearophile

I know that there are other ways that'll work.  I was just curious about what appears to be a surprise in the way that foreach interacts with stdio.lines.

Andrew

December 11, 2014
On Thursday, 11 December 2014 at 20:11:21 UTC, Andrew Klaassen wrote:
> The docs for stdio.lines say that it's a struct.  stdio.lines works with foreach.
>
> The docs for foreach say:
>
> "Iteration over struct and class objects can be done with ranges. For foreach, this means the following properties and methods must be defined: .empty ... .front ... .popFront()"
>
> But when I try to access any of those properties or methods for stdio.lines, I get compilation errors:
>
>   1 import io = std.stdio;
>   2
>   3 void main(string[] args) {
>   4
>   5     auto infile = io.File(args[1], "r");
>   6
>   7     auto filelines = io.lines(infile);
>   8
>   9     io.writeln(filelines.front);
>  10     io.writeln(filelines.empty);
>  11     io.writeln(filelines.popFront());
>  12 }
>
> test_filechunking.d(9): Error: no property 'front' for type 'lines'
> test_filechunking.d(10): Error: no property 'empty' for type 'lines'
> test_filechunking.d(11): Error: no property 'popFront' for type 'lines'
>
> Why is this?
>
> I'm using ldc2 for compilation, FWIW.
>
> Andrew

Ranges are one way of allowing foreach. The other is through the use of opApply, which is what std.stdio.lines does.

http://dlang.org/statement.html#ForeachStatement
December 11, 2014
On 12/11/14 3:21 PM, Andrew Klaassen wrote:
> On Thursday, 11 December 2014 at 20:17:50 UTC, bearophile wrote:
>> Andrew Klaassen:
>>
>>> The docs for stdio.lines say that it's a struct.  stdio.lines works
>>> with foreach.
>>
>> If you want a range use "myfile".File.byLine or "myfile".File.byLineCopy.
>>
>> Bye,
>> bearophile
>
> I know that there are other ways that'll work.  I was just curious about
> what appears to be a surprise in the way that foreach interacts with
> stdio.lines.

Look down a little bit further on that document, you will see the section titled "Foreach over Structs and Classes with opApply"

Hm.. I note the incorrect statement "If the range properties don't exist, then the foreach is defined by the opApply member function". This is not exactly true, the foreach statement defaults to opApply first, and will use range functions only if that doesn't exist.

FYI, the reason stdio.lines works that way is because in general, ranges can only give you one value, but stdio.lines wants to give you the line number too.

-Steve
December 11, 2014
On Thursday, 11 December 2014 at 20:37:09 UTC, Kapps wrote:
> Ranges are one way of allowing foreach. The other is through the use of opApply, which is what std.stdio.lines does.
>
> http://dlang.org/statement.html#ForeachStatement

Ah, so I just needed to keep reading down a few lines in the foreach docs.  Thanks!

Andrew