Re: input range with non copyable element

2021-08-09 Thread vit via Digitalmars-d-learn

On Monday, 9 August 2021 at 02:47:40 UTC, Mathias LANG wrote:

On Sunday, 8 August 2021 at 18:36:02 UTC, vit wrote:
Hello, is there reason why elements of input range must be 
copyable?


By design, not that I can think of. But it is assumed all over 
the place, unfortunately. You can make your `front` method 
return by `ref`, but you're still going to get bitten as soon 
as you do any `std.algorithm`-based operation, as storage 
classes are not inferred 
(https://issues.dlang.org/show_bug.cgi?id=9423) and things get 
passed by value to your delegates by default. The problem can 
also show up when you `foreach` over a range 
(https://issues.dlang.org/show_bug.cgi?id=15413). And finally, 
`std.algorithm` need to support it.


So currently you'll have to jump through a lot of hops to get 
it to work. It'll be much easier to use your own `map` & co to 
get the job done for the time being. Hopefully at some point in 
the near future that won't be needed anymore.


Look like I am not the first who has this problem: 
https://issues.dlang.org/show_bug.cgi?id=14478



I copy part of `std.algorithm` I use and change `isInputRange` to:
```d
enum bool isInputRange(R) = true
&& is(typeof(R.init) == R)  
///no change
&& is(ReturnType!((R r) => r.empty) == bool) 
///no change
	&& is(typeof((return ref R r) => (auto ref 
x){}(r.front)))	///Before: , is(typeof((return ref R r) => 
r.front))

&& !is(ReturnType!((R r) => r.front) == void)
///no change
&& is(typeof((R r) => r.popFront)); 
 ///no change



Re: input range with non copyable element

2021-08-08 Thread Mathias LANG via Digitalmars-d-learn

On Sunday, 8 August 2021 at 18:36:02 UTC, vit wrote:
Hello, is there reason why elements of input range must be 
copyable?


By design, not that I can think of. But it is assumed all over 
the place, unfortunately. You can make your `front` method return 
by `ref`, but you're still going to get bitten as soon as you do 
any `std.algorithm`-based operation, as storage classes are not 
inferred (https://issues.dlang.org/show_bug.cgi?id=9423) and 
things get passed by value to your delegates by default. The 
problem can also show up when you `foreach` over a range 
(https://issues.dlang.org/show_bug.cgi?id=15413). And finally, 
`std.algorithm` need to support it.


So currently you'll have to jump through a lot of hops to get it 
to work. It'll be much easier to use your own `map` & co to get 
the job done for the time being. Hopefully at some point in the 
near future that won't be needed anymore.


input range with non copyable element

2021-08-08 Thread vit via Digitalmars-d-learn
Hello, is there reason why elements of input range must be 
copyable?


For example this example works and copy ctor is never called:

```d
import std.algorithm : map;
import std.range;

struct Foo{
int i;

this(scope ref typeof(this) rhs)pure nothrow @safe @nogc{
//this.i = rhs.i;
assert(0, "no copy");
}
	@disable this(scope const ref typeof(this) rhs)pure nothrow 
@safe @nogc;

}


void main(){
Foo[] foos = [Foo(1), Foo(2), Foo(3)];

//this work (copy ctor is never called):
{
auto tmp = foos
.map!((ref foo) => foo.i)
.array;
}
}
```

This doesn't work:


```d

void main(){
const(Foo)[] foos = [Foo(1), Foo(2), Foo(3)];

//error:
{
auto tmp = foos
.map!((ref foo) => foo.i)
.array;
}
}
```

Source of my problem is in `isInputRange`:
```d
import std.range;
import std.traits : ReturnType;

alias R = const(Foo)[];
//enum bool isInputRange(R) =
static assert(is(typeof(R.init) == R)); 
///OK
static assert(is(ReturnType!((R r) => r.empty) == bool));
///OK
static assert(is(typeof((return ref R r) => 
r.front)));///ERROR, copy result of front

static assert(!is(ReturnType!((R r) => r.front) == void));   
///OK
static assert(is(typeof((R r) => r.popFront))); 
 ///OK
```

Is it possible to make lambda return `auto ref`?