digitalmars.D - error with std.range.put - readN
- Baz (29/29) May 04 2015 the following program fails because of the `put` function :
- sclytrack (27/56) May 04 2015 I believe the put(R,E) calls the doPut(R, E)
- Jonathan M Davis (12/41) May 04 2015 Your destination is too small. When arrays are treated as output
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (14/16) May 04 2015 In addition to what others said, even if dst had room for two elements,
- Jonathan M Davis (10/26) May 04 2015 I really think that output ranges need to be rethought through.
the following program fails because of the `put` function :
---
import std.stdio;
import std.range;
size_t readN(T, Range)(ref Range src, ref Range dst, size_t n)
if (isInputRange!Range && isOutputRange!(Range, T))
{
size_t result;
while(1)
{
if (src.empty || result == n)
break;
put(dst, src.front()); // here
src.popFront;
++result;
}
return result;
}
void main(string[] args)
{
int[] src = [1,2,3];
int[] dst = [0];
auto n = readN!int(src, dst, 2);
writeln(dst);
}
---
If i replace `put` by a cat op (`~`) it works, however the cat op
only works here because i test the template with two int[].
What's wrong ?
May 04 2015
On Monday, 4 May 2015 at 14:33:23 UTC, Baz wrote:
the following program fails because of the `put` function :
---
import std.stdio;
import std.range;
size_t readN(T, Range)(ref Range src, ref Range dst, size_t n)
if (isInputRange!Range && isOutputRange!(Range, T))
{
size_t result;
while(1)
{
if (src.empty || result == n)
break;
put(dst, src.front()); // here
src.popFront;
++result;
}
return result;
}
void main(string[] args)
{
int[] src = [1,2,3];
int[] dst = [0];
auto n = readN!int(src, dst, 2);
writeln(dst);
}
---
If i replace `put` by a cat op (`~`) it works, however the cat
op only works here because i test the template with two int[].
What's wrong ?
I believe the put(R,E) calls the doPut(R, E)
private void doPut(R, E)(ref R r, auto ref E e)
{
//...
else static if (isInputRange!R)
{
static assert(is(typeof(r.front = e)),
"Cannot nativaly put a " ~ E.stringof ~ " into a " ~
R.stringof ~ ".");
r.front = e;
r.popFront();
}
//...
}
So basically you put elements into the list until it is empty.
import std.stdio;
import std.range;
void main()
{
int [] list = new int [10];
writeln(list); //10 zeros
list.front = 5; //1 five and 9 zeroes
writeln(list);
list.popFront(); //9 zeroes left.
writeln(list);
}
May 04 2015
On Monday, 4 May 2015 at 14:33:23 UTC, Baz wrote:
the following program fails because of the `put` function :
---
import std.stdio;
import std.range;
size_t readN(T, Range)(ref Range src, ref Range dst, size_t n)
if (isInputRange!Range && isOutputRange!(Range, T))
{
size_t result;
while(1)
{
if (src.empty || result == n)
break;
put(dst, src.front()); // here
src.popFront;
++result;
}
return result;
}
void main(string[] args)
{
int[] src = [1,2,3];
int[] dst = [0];
auto n = readN!int(src, dst, 2);
writeln(dst);
}
---
If i replace `put` by a cat op (`~`) it works, however the cat
op only works here because i test the template with two int[].
What's wrong ?
Your destination is too small. When arrays are treated as output
ranges, they get written to like a buffer. They don't get
appended to. If you want to append to them, then use Appender for
the output range.
On a side note, it's very backwards that you're calling front
with parens and popFront without. front is usually a property
function (in which case, if property ever gets sorted out
properly, front() wouldn't compile), and popFront is never a
property function (so you _can_ call it without parens, but it's
kind of weird to do so).
- Jonathan M Davis
May 04 2015
On 05/04/2015 07:33 AM, Baz wrote:
int[] src = [1,2,3];
int[] dst = [0];
In addition to what others said, even if dst had room for two elements,
it would lose the newly added element due to a popFront() called
implicitly during put()'ting.
int[] dst = [0, 0]; // <-- Has room now
auto n = readN!int(src, dst, 2);
writeln(dst); // <-- Prints "[]" WAT?
One solution is to introduce another slice that would not be popFront'ed:
int[] dst = [0, 0];
int[] dst2 = dst; // <-- This
auto n = readN!int(src, dst, 2);
writeln(dst2); // <-- prints "[1, 2]"
However, Appender is a better solution.
Ali
May 04 2015
On Monday, 4 May 2015 at 18:50:45 UTC, Ali Çehreli wrote:On 05/04/2015 07:33 AM, Baz wrote:I really think that output ranges need to be rethought through. In most cases, lazy input ranges should be used instead, but they do have their uses. The problem is that they're not designed well enough or thoroughly enough to be very useful outside of Appender. Using arrays as output ranges is particularly bad, but the fact that there is no way to know whether an output range even has room to put a new element or range of elements onto its end makes output ranges unusable in many cases IMHO. - Jonathan M Davisint[] src = [1,2,3]; int[] dst = [0];In addition to what others said, even if dst had room for two elements, it would lose the newly added element due to a popFront() called implicitly during put()'ting. int[] dst = [0, 0]; // <-- Has room now auto n = readN!int(src, dst, 2); writeln(dst); // <-- Prints "[]" WAT? One solution is to introduce another slice that would not be popFront'ed: int[] dst = [0, 0]; int[] dst2 = dst; // <-- This auto n = readN!int(src, dst, 2); writeln(dst2); // <-- prints "[1, 2]" However, Appender is a better solution.
May 04 2015









"sclytrack" <sclytrack fake.com> 