February 11, 2014
On Tuesday, 11 February 2014 at 10:52:40 UTC, Tobias Pankrath wrote:

>
> The second naive solution would be to use readText and splitLines.

That's the sort of thing I always do because then I understand what's going on, and when there's a bug I can find it easily!

But then I'm not writing libraries.

Steve

February 11, 2014
On Tuesday, 11 February 2014 at 13:00:19 UTC, Regan Heath wrote:
> import std.stdio;
>
> struct S1 {
>    private int[] elements = [9,8,7];
>    int opApply (int delegate (ref uint, ref int) block) {
>        foreach (uint i, int n ; this.elements)
>            block(i, n);
>        return 0;
>    }
> }
>
> void main()
> {
> 	S1 range;

S1 is not a range. But this is a correct response to "Is foreach(i, val; aggregate) even defined if aggr is not an array or associated array?"
February 11, 2014
On Tue, 11 Feb 2014 05:10:27 -0500, Regan Heath <regan@netmail.co.nz> wrote:

> Things like this should "just work"..
>
> File input ...
>
> auto range = input.byLine();
> while(!range.empty)
> {
>    range.popFront();
>    foreach (i, line; range.take(4))  //Error: cannot infer argument types
>    {
>      ..etc..
>    }
>    range.popFront();
> }
>
> Tried adding 'int' and 'char[]' or 'auto' .. no dice.
>
> Can someone explain why this fails, and if this is a permanent or temporary limitation of D/MD.

This is only available using opApply style iteration. Using range iteration does not give you this ability.

It's not a permanent limitation per se, but there is no plan at the moment to add multiple parameters to range iteration.

One thing that IS a limitation though: we cannot overload on return values. So the obvious idea of overloading front to return tuples of various types, would not be feasible. opApply can do that because the delegate is a parameter.

-Steve
February 11, 2014
On Tuesday, 11 February 2014 at 10:10:27 UTC, Regan Heath wrote:
> Things like this should "just work"..
>
> File input ...
>
> auto range = input.byLine();
> while(!range.empty)
> {
>   range.popFront();
>   foreach (i, line; range.take(4))  //Error: cannot infer argument types
>   {
>     ..etc..
>   }
>   range.popFront();
> }
>
> Tried adding 'int' and 'char[]' or 'auto' .. no dice.
>
> Can someone explain why this fails, and if this is a permanent or temporary limitation of D/MD.
>
> R

In case the other replies weren't clear enough. A range does not have an index.

What do you expect 'i' to be? Is it the line number? Is it the index within the line where 'take' begins? Where 'take' stops?

There is a feature of foreach and tuple() which results in the tuple getting expanded automatically.

byLine has its own issues with reuse of the buffer, it isn't inherent to ranges. I haven't really used it (needed it from std.process), when I wanted to read a large file I went with wrapping std.mmap:

https://github.com/JesseKPhillips/libosm/blob/master/source/util/filerange.d
February 12, 2014
On Tuesday, 11 February 2014 at 19:48:41 UTC, Jesse Phillips wrote:

> In case the other replies weren't clear enough. A range does not have an index.
>
> What do you expect 'i' to be?

In case of foreach(i, x; range) I would expect it to be iteration number of this particular foreach. I miss it sometimes, have to create another variable and increment it. I didn't know about automatic tuple expansion though, that looks better.
February 12, 2014
On Tue, 11 Feb 2014 17:11:46 -0000, Ali Çehreli <acehreli@yahoo.com> wrote:

> On 02/11/2014 06:25 AM, Rene Zwanenburg wrote:
>> On Tuesday, 11 February 2014 at 10:10:27 UTC, Regan Heath wrote:
>
>>>   foreach (i, line; range.take(4))  //Error: cannot infer argument types
>>>   {
>>>     ..etc..
>>>   }
>
>> foreach (i, line; iota(size_t.max).zip(range.take(4)))
>> {
>>
>> }
>
> There is also the following, relying on tuples' automatic expansion in foreach:
>
>      foreach (i, element; zip(sequence!"n", range.take(4))) {
>          // ...
>      }

Thanks for the workarounds.  :)  Both seem needlessly opaque, but I realise you're not suggesting these are better than the original, just that they actually work today.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
February 12, 2014
On Tue, 11 Feb 2014 13:11:54 -0000, Tobias Pankrath <tobias@pankrath.net> wrote:

> On Tuesday, 11 February 2014 at 13:00:19 UTC, Regan Heath wrote:
>> import std.stdio;
>>
>> struct S1 {
>>    private int[] elements = [9,8,7];
>>    int opApply (int delegate (ref uint, ref int) block) {
>>        foreach (uint i, int n ; this.elements)
>>            block(i, n);
>>        return 0;
>>    }
>> }
>>
>> void main()
>> {
>> 	S1 range;	
>> 	foreach(uint i, int x; range)
>> 	{
>> 	  writefln("%d is %d", i, x);
>> 	}
>> }
>>
>> R
>
> byLine does not use opApply
> https://github.com/D-Programming-Language/phobos/blob/master/std/stdio.d#L1389

Ahh.. so this is a limitation of the range interface.  Any plans to "fix" this?

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
February 12, 2014
On Tue, 11 Feb 2014 19:08:18 -0000, Jesse Phillips <Jesse.K.Phillips+D@gmail.com> wrote:

> On Tuesday, 11 February 2014 at 13:00:19 UTC, Regan Heath wrote:
>> import std.stdio;
>>
>> struct S1 {
>>    private int[] elements = [9,8,7];
>>    int opApply (int delegate (ref uint, ref int) block) {
>>        foreach (uint i, int n ; this.elements)
>>            block(i, n);
>>        return 0;
>>    }
>> }
>>
>> void main()
>> {
>> 	S1 range;
>
> S1 is not a range. But this is a correct response to "Is foreach(i, val; aggregate) even defined if aggr is not an array or associated array?"

True, but then I had missed the fact that there are two distinct mechanisms (opApply/range) in play here.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
February 12, 2014
On Tue, 11 Feb 2014 19:16:31 -0000, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> On Tue, 11 Feb 2014 05:10:27 -0500, Regan Heath <regan@netmail.co.nz> wrote:
>
>> Things like this should "just work"..
>>
>> File input ...
>>
>> auto range = input.byLine();
>> while(!range.empty)
>> {
>>    range.popFront();
>>    foreach (i, line; range.take(4))  //Error: cannot infer argument types
>>    {
>>      ..etc..
>>    }
>>    range.popFront();
>> }
>>
>> Tried adding 'int' and 'char[]' or 'auto' .. no dice.
>>
>> Can someone explain why this fails, and if this is a permanent or temporary limitation of D/MD.
>
> This is only available using opApply style iteration. Using range iteration does not give you this ability.
>
> It's not a permanent limitation per se, but there is no plan at the moment to add multiple parameters to range iteration.
>
> One thing that IS a limitation though: we cannot overload on return values. So the obvious idea of overloading front to return tuples of various types, would not be feasible. opApply can do that because the delegate is a parameter.

Thanks for the concise/complete response.  I had managed to piece this together from other replies but it's clearer now.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
February 12, 2014
On Tue, 11 Feb 2014 19:48:40 -0000, Jesse Phillips <Jesse.K.Phillips+D@gmail.com> wrote:

> On Tuesday, 11 February 2014 at 10:10:27 UTC, Regan Heath wrote:
>> Things like this should "just work"..
>>
>> File input ...
>>
>> auto range = input.byLine();
>> while(!range.empty)
>> {
>>   range.popFront();
>>   foreach (i, line; range.take(4))  //Error: cannot infer argument types
>>   {
>>     ..etc..
>>   }
>>   range.popFront();
>> }
>>
>> Tried adding 'int' and 'char[]' or 'auto' .. no dice.
>>
>> Can someone explain why this fails, and if this is a permanent or temporary limitation of D/MD.
>>
>> R
>
> In case the other replies weren't clear enough. A range does not have an index.

It isn't *required* to (input/forward), but it could (random access).  I think we even have a template to test if it's indexable as we can optimise some algorithms based on this.

> What do you expect 'i' to be? Is it the line number? Is it the index within the line where 'take' begins? Where 'take' stops?

If I say take(5) I expect 0,1,2,3,4.  The index into the take range itself.

The reason I wanted it was I was parsing blocks of data over 6 lines - I wanted to ignore the first and last and process the middle 4.  In fact I wanted to skip the 2nd of those 4 as well, but there was not single function (I could find) which would do all that so I coded the while above.

> There is a feature of foreach and tuple() which results in the tuple getting expanded automatically.

And also the opApply overload taking a delegate with both parameters.

> byLine has its own issues with reuse of the buffer, it isn't inherent to ranges. I haven't really used it (needed it from std.process), when I wanted to read a large file I went with wrapping std.mmap:
>
> https://github.com/JesseKPhillips/libosm/blob/master/source/util/filerange.d

Cool, thanks.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/