Re: RefRange behavior

2018-03-14 Thread Alex via Digitalmars-d-learn

On Wednesday, 14 March 2018 at 10:22:45 UTC, Alex wrote:

Is there a simple workaround, maybe?


ok, the workaround would be to enumerate the member and to use 
the former notation.




RefRange behavior

2018-03-14 Thread Alex via Digitalmars-d-learn

Hi all,
given this:

´´´
import std.range;

size_t[] arr;

struct S
{
RefRange!(size_t[]) member;
}

void fun(ref size_t numByRef){}

void main()
{
arr.length = 42;
S s;
s.member = refRange();
static assert(__traits(compiles, fun(s.member[0])));
static assert(!__traits(compiles, fun(s.member.front)));
//fun(s.member.front);
/*
	source/app.d(19,5): Error: function `app.fun(ref ulong 
numByRef)` is not callable using argument types `(ulong)`
	source/app.d(19,5):cannot pass rvalue argument 
`s.member.front()` of type `ulong` to parameter `ref ulong 
numByRef`

*/
}
´´´

Why does the last static assert yields false? Is there a simple 
workaround, maybe?


Re: refRange with non copyable struct

2017-04-17 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, April 17, 2017 19:39:25 Stanislav Blinov via Digitalmars-d-learn 
wrote:
> On Monday, 17 April 2017 at 19:00:44 UTC, Jonathan M Davis wrote:
> > Because otherwise, it's not acting like a reference to the
> > original range, which is the whole point of RefRange. The
> > correct solution would probably be to @disable opAssign in the
> > case where the original range can't be overwritten by another
> > range.
>
> This doesn't look quite right. References in D are rebindable.
> That is, assigning a reference to a reference does not copy
> referenced object, only the reference itself.
> It seems that RefRange is trying to impersonate a C++ reference.

The term reference in D is a bit overloaded. The whole point of RefRange is
to have the original range affected by everything that happens to the new
range as if it were the original range - which is what happens with ref
(which is not rebindable) except that ref only works on parameters and
return types. So, yes, it is similar to a C++ reference. It's not trying to
be a pointer, which is more like what a class reference is.

- Jonathan M Davis



Re: refRange with non copyable struct

2017-04-17 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 17 April 2017 at 19:00:44 UTC, Jonathan M Davis wrote:

Because otherwise, it's not acting like a reference to the 
original range, which is the whole point of RefRange. The 
correct solution would probably be to @disable opAssign in the 
case where the original range can't be overwritten by another 
range.


This doesn't look quite right. References in D are rebindable. 
That is, assigning a reference to a reference does not copy 
referenced object, only the reference itself.

It seems that RefRange is trying to impersonate a C++ reference.


Re: refRange with non copyable struct

2017-04-17 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, April 17, 2017 18:45:46 Jerry via Digitalmars-d-learn wrote:
> On Monday, 17 April 2017 at 18:07:36 UTC, Jonathan M Davis wrote:
> > In this particular case, it looks like the main problem is
> > RefRange's opAssign. For it to work, the type needs to be
> > copyable. It might be reasonable for RefRange to be enhanced so
> > that it doesn't compile in opAssign if the range isn't
> > copyable, but I'd have to study RefRange in depth to know what
> > the exact consequences of that would be, since it's been quite
> > a while since I did anything with it. My guess is that such a
> > change would be reasonable, but I don't know without studying
> > it.
> >
> > - Jonathan M Davis
>
> I took a look on RefRange and the reasoning is clearly explained
> in the docs like this:
>
> This does not assign the pointer of $(D rhs) to this $(D
> RefRange).
> Rather it assigns the range pointed to by $(D rhs) to the range
> pointed
> to by this $(D RefRange). This is because $(I any) operation on a
> RefRange) is the same is if it occurred to the original range. The
> exception is when a $(D RefRange) is assigned $(D null) either
> or because $(D rhs) is $(D null). In that case, $(D RefRange)
> longer refers to the original range but is $(D null).
>
>
>
> But what I do not understand is why this is important.

Because otherwise, it's not acting like a reference to the original range,
which is the whole point of RefRange. The correct solution would probably be
to @disable opAssign in the case where the original range can't be
overwritten by another range.

- Jonathan M Davis



Re: refRange with non copyable struct

2017-04-17 Thread Jerry via Digitalmars-d-learn

On Monday, 17 April 2017 at 18:07:36 UTC, Jonathan M Davis wrote:
In this particular case, it looks like the main problem is 
RefRange's opAssign. For it to work, the type needs to be 
copyable. It might be reasonable for RefRange to be enhanced so 
that it doesn't compile in opAssign if the range isn't 
copyable, but I'd have to study RefRange in depth to know what 
the exact consequences of that would be, since it's been quite 
a while since I did anything with it. My guess is that such a 
change would be reasonable, but I don't know without studying 
it.


- Jonathan M Davis


I took a look on RefRange and the reasoning is clearly explained 
in the docs like this:


This does not assign the pointer of $(D rhs) to this $(D 
RefRange).
Rather it assigns the range pointed to by $(D rhs) to the range 
pointed

to by this $(D RefRange). This is because $(I any) operation on a
RefRange) is the same is if it occurred to the original range. The
exception is when a $(D RefRange) is assigned $(D null) either
or because $(D rhs) is $(D null). In that case, $(D RefRange)
longer refers to the original range but is $(D null).



But what I do not understand is why this is important.


Re: refRange with non copyable struct

2017-04-17 Thread Jerry via Digitalmars-d-learn

On Monday, 17 April 2017 at 18:07:36 UTC, Jonathan M Davis wrote:

Non-copyable types tend to wreak havoc with things
- Jonathan M Davis


Basicly what I use this for is to combine RAII with ranges.
Which I find quite useful when doing DB queries and the data is 
lazily fetched
since this allows me to guarantee that the query is "closed" and 
another query can take place.




Re: refRange with non copyable struct

2017-04-17 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, April 17, 2017 17:23:32 Jerry via Digitalmars-d-learn wrote:
> Hello guys, so I wanted to have a noncopyable range on the stack.
> So my thoughts was to make it non copyable and use refRange
> whenever I want to use it with map and others.
>
> But I got a compiler warning when doing so like this:
>
> import std.range;
>
> void main() {
>   NonCopyable v;
>
>   refRange();
> }
>
> struct NonCopyable
> {
>   @disable this(this);
>
>   int data;
>
>   enum empty = false;
>   void popFront() {}
>   int front() { return data; }
> }
>
>
>
>
>
> With the error message:
>
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(8941):
> Error: struct reproduction.NonCopyable is not copyable because it
> is annotated with @disable
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(8982):
> Error: mutable method reproduction.NonCopyable.front is not
> callable using a const object
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(9649):
> Error: template instance std.range.RefRange!(NonCopyable) error
> instantiating
> reproduction.d(6):instantiated from here:
> refRange!(NonCopyable)
>
>
>
>
> Is there any workaround?
> Is this a bug?

Well, I don't think that much range-based code in general is going to work
with a disabled postblit constructor, and it's not something that's
generally tested for unless someone is specifically trying to use such a
type with a specific piece of code. Non-copyable types tend to wreak havoc
with things - not that they shouldn't necessarily work, but most stuff tends
to assume that types are copyable, and supporting non-copyable often
complicates things quite a bit. Most of Phobos simply hasn't been tested
with non-copyable types even if the functionality in question should
arguably work with them.

In this particular case, it looks like the main problem is RefRange's
opAssign. For it to work, the type needs to be copyable. It might be
reasonable for RefRange to be enhanced so that it doesn't compile in
opAssign if the range isn't copyable, but I'd have to study RefRange in
depth to know what the exact consequences of that would be, since it's been
quite a while since I did anything with it. My guess is that such a change
would be reasonable, but I don't know without studying it.

- Jonathan M Davis



refRange with non copyable struct

2017-04-17 Thread Jerry via Digitalmars-d-learn

Hello guys, so I wanted to have a noncopyable range on the stack.
So my thoughts was to make it non copyable and use refRange 
whenever I want to use it with map and others.


But I got a compiler warning when doing so like this:

import std.range;

void main() {
NonCopyable v;

refRange();
}

struct NonCopyable
{
@disable this(this);

int data;

enum empty = false;
void popFront() {}
int front() { return data; }
}





With the error message:

C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(8941): 
Error: struct reproduction.NonCopyable is not copyable because it 
is annotated with @disable
C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(8982): 
Error: mutable method reproduction.NonCopyable.front is not 
callable using a const object
C:\D\dmd2\windows\bin\..\..\src\phobos\std\range\package.d(9649): 
Error: template instance std.range.RefRange!(NonCopyable) error 
instantiating
reproduction.d(6):instantiated from here: 
refRange!(NonCopyable)





Is there any workaround?
Is this a bug?


RefRange

2012-08-26 Thread David
It's a RefRange, but not completly ... Can somebody explain me that 
behaviour?


http://dpaste.dzfl.pl/643de2a3


Re: RefRange

2012-08-26 Thread Ali Çehreli

On 08/26/2012 08:41 AM, David wrote:

It's a RefRange, but not completly ... Can somebody explain me that
behaviour?

http://dpaste.dzfl.pl/643de2a3


According to its documentation, RefRange works differently whether the 
original range is a ForwardRange or not:


  http://dlang.org/phobos/std_range.html#refRange

I have made TestRange a ForwardRange but then I had to comment out two 
lines of your program. Does it work according to your expectations with 
this change?


import std.stdio;
import std.range;

struct TestRange {
float[] x = [0, 1, 2, 3, 4, 5];

@property bool empty() {
return x.length == 0;
}

@property ref float front() {
return x[0];
}

void popFront() {
//writefln(before: %s, x);
x = x[1..$];
//x.popFront();
//writefln(after: %s, x);
}

TestRange save() @property {
return TestRange(x);
}
}



void main() {
static assert(isForwardRange!TestRange);

TestRange r = TestRange();
auto rr = refRange(r);

//foreach(element; rr) {}

//writefln(Original range: %s, r.x);
//writefln(RefRange: %s, rr.x);

writefln(%s - %s, r.x.ptr, r.x.ptr);

rr.popFront();

writefln(%s - %s, r.x.ptr, r.x.ptr);
writefln(Original range: %s, r.x);
// We can't expect the RefRange to have the members of the original 
range

// writefln(RefRange: %s, rr.x);

r.popFront();

writefln(%s - %s, r.x.ptr, r.x.ptr);
writefln(Original range: %s, r.x);
// We can't expect the RefRange to have the members of the original 
range

// writefln(RefRange: %s, rr.x);
}

Ali


Re: RefRange

2012-08-26 Thread Jonathan M Davis
On Sunday, August 26, 2012 17:41:45 David wrote:
 It's a RefRange, but not completly ... Can somebody explain me that
 behaviour?

 http://dpaste.dzfl.pl/643de2a3

refRange simply returns the original range if it's an input range rather than 
a forward range, since normally, when you have an input range, it isn't a 
value type, and there's no way to copy it, so operating on one reference of it 
is already the same as operating on all of them, making RefRange pointless.

However, you've done the odd thing of declaring a value type input range. I 
don't know why that would ever be done except through ignorance of how ranges 
work. So, refRange is actually returning a copy in your case, which is why 
you're having problems.

And by the way, the only reason that rr.x works is because refRange is 
returning a copy rather than a RefRange!TestRange.

- Jonathan M Davis


Re: RefRange

2012-08-26 Thread Jonathan M Davis
On Sunday, August 26, 2012 10:17:13 Jonathan M Davis wrote:
 On Sunday, August 26, 2012 17:41:45 David wrote:
  It's a RefRange, but not completly ... Can somebody explain me that
  behaviour?
  
  http://dpaste.dzfl.pl/643de2a3
 
 refRange simply returns the original range if it's an input range rather
 than a forward range, since normally, when you have an input range, it
 isn't a value type, and there's no way to copy it, so operating on one
 reference of it is already the same as operating on all of them, making
 RefRange pointless.
 
 However, you've done the odd thing of declaring a value type input range. I
 don't know why that would ever be done except through ignorance of how
 ranges work. So, refRange is actually returning a copy in your case, which
 is why you're having problems.

Though the fact that you ran into this issue may indicate that having refRange 
return the original if it isn't a forward range was a bad decision. I don't 
know. In the normal case, it's definitely better, because it avoids an 
unnecessary wrapper, but obviously, people can make mistakes. You should still 
be able use RefRange with an input range though, as long as you use it 
directly.

auto wrapped = RefRange!TestRange(orig);

But it would be better IMHO to just fix it so that your range is a forward 
range, since there's no reason for it not to be.

- Jonathan M Davis


Re: RefRange

2012-08-26 Thread David

Am 26.08.2012 20:07, schrieb Jonathan M Davis:

On Sunday, August 26, 2012 10:17:13 Jonathan M Davis wrote:

On Sunday, August 26, 2012 17:41:45 David wrote:

It's a RefRange, but not completly ... Can somebody explain me that
behaviour?

http://dpaste.dzfl.pl/643de2a3


refRange simply returns the original range if it's an input range rather
than a forward range, since normally, when you have an input range, it
isn't a value type, and there's no way to copy it, so operating on one
reference of it is already the same as operating on all of them, making
RefRange pointless.

However, you've done the odd thing of declaring a value type input range. I
don't know why that would ever be done except through ignorance of how
ranges work. So, refRange is actually returning a copy in your case, which
is why you're having problems.


Though the fact that you ran into this issue may indicate that having refRange
return the original if it isn't a forward range was a bad decision. I don't
know. In the normal case, it's definitely better, because it avoids an
unnecessary wrapper, but obviously, people can make mistakes. You should still
be able use RefRange with an input range though, as long as you use it
directly.

auto wrapped = RefRange!TestRange(orig);

But it would be better IMHO to just fix it so that your range is a forward
range, since there's no reason for it not to be.

- Jonathan M Davis



Ranges died another time for me. This refRange copy thingy cost me lots 
of time, then I tried to implement a .save method, which uhm, just 
didn't work together with RefRange (isForwardRange!T succeeded, but 
isForwardRange!(RefRange!T) failed).


Anyways, thanks for your explanations!


Re: RefRange

2012-08-26 Thread David

Am 26.08.2012 18:06, schrieb Ali Çehreli:

On 08/26/2012 08:41 AM, David wrote:

It's a RefRange, but not completly ... Can somebody explain me that
behaviour?

http://dpaste.dzfl.pl/643de2a3


According to its documentation, RefRange works differently whether the
original range is a ForwardRange or not:

   http://dlang.org/phobos/std_range.html#refRange

I have made TestRange a ForwardRange but then I had to comment out two
lines of your program. Does it work according to your expectations with
this change?

import std.stdio;
import std.range;

struct TestRange {
 float[] x = [0, 1, 2, 3, 4, 5];

 @property bool empty() {
 return x.length == 0;
 }

 @property ref float front() {
 return x[0];
 }

 void popFront() {
 //writefln(before: %s, x);
 x = x[1..$];
 //x.popFront();
 //writefln(after: %s, x);
 }

 TestRange save() @property {
 return TestRange(x);
 }
}



void main() {
 static assert(isForwardRange!TestRange);

 TestRange r = TestRange();
 auto rr = refRange(r);

 //foreach(element; rr) {}

 //writefln(Original range: %s, r.x);
 //writefln(RefRange: %s, rr.x);

 writefln(%s - %s, r.x.ptr, r.x.ptr);

 rr.popFront();

 writefln(%s - %s, r.x.ptr, r.x.ptr);
 writefln(Original range: %s, r.x);
 // We can't expect the RefRange to have the members of the original
range
 // writefln(RefRange: %s, rr.x);

 r.popFront();

 writefln(%s - %s, r.x.ptr, r.x.ptr);
 writefln(Original range: %s, r.x);
 // We can't expect the RefRange to have the members of the original
range
 // writefln(RefRange: %s, rr.x);
}

Ali


Yes, that does it, but .save doesn't play well with RefRange (a static 
assert inside RefRange fails, telling that the produced RefRange-Type is 
not a ForwardRange).


Re: RefRange

2012-08-26 Thread Ali Çehreli

On 08/26/2012 02:21 PM, David wrote:

 I tried to implement a .save method, which uhm, just
 didn't work together with RefRange (isForwardRange!T succeeded, but
 isForwardRange!(RefRange!T) failed).

What version of dmd? What is the code?

When I add the following lines to the beginning of main() of the program 
that I have used in my other post, they both pass:


static assert(isForwardRange!TestRange);
static assert(isForwardRange!(RefRange!TestRange));

Ali



Re: RefRange

2012-08-26 Thread David

Am 26.08.2012 23:33, schrieb Ali Çehreli:

On 08/26/2012 02:21 PM, David wrote:

  I tried to implement a .save method, which uhm, just
  didn't work together with RefRange (isForwardRange!T succeeded, but
  isForwardRange!(RefRange!T) failed).

What version of dmd? What is the code?

When I add the following lines to the beginning of main() of the program
that I have used in my other post, they both pass:

 static assert(isForwardRange!TestRange);
 static assert(isForwardRange!(RefRange!TestRange));

Ali



DMD 2.059 and: 
https://github.com/Dav1dde/BraLa/blob/7440688038bfd50a06fd9a49b8e9b6d08c7b4c28/brala/utils/queue.d


But I don't care anylonger, I rewrote the whole Queue class (now it's a 
real queue, e.g. you can wait until all items are used up, with 
core.sync.condtion), I also don't feel like wasting more time in ranges, 
when I don't need them.