www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why does inputRangeObject fail to derive correctly for

reply D Lark <dlark example.com> writes:
This is slightly related to this issue I reported earlier: 
https://forum.dlang.org/post/wghdwxptjfcjwptnybhn forum.dlang.org

Here's the snippet that captures what fails for me

```dlang
     import std.range: ElementType, isRandomAccessRange, 
inputRangeObject, sequence, MostDerivedInputRange, 
RandomAccessInfinite;

     auto seq = sequence!((a, n) => n);
     alias SeqType = typeof(seq);
     static assert(isRandomAccessRange!SeqType);

     static assert(is(MostDerivedInputRange!SeqType == 
RandomAccessInfinite!(ElementType!SeqType)));

     auto seqInputRange = seq.inputRangeObject;
     static assert(isRandomAccessRange!(typeof(seqInputRange))); 
// returns 'false'; I expect this to return 'true' as the most 
derived type of 'seq' is of 'RandomAccessInfinite' as 
demonstrated above

```
I am compiling using dmd v2.100.1

First, please can someone clarify if the behaviour I expect in 
the last line is consistent with the intention of the library?

I have poked around the source and I can see that the 
`InputRangeObject` (the object returned by `inputRangeObject` 
derives from the return type of the `MostDerivedInputRange` 
template, which as shown above returns the correct interface. 
However it seems that the implementation of `InputRangeObject` 
does not implement `enum bool empty = false` in the case of the 
`RandomAccessInfinite` ranges, which leads to the template 
`isRandomAccessRange` returning false.
Jul 12 2022
parent reply Paul Backus <snarwin gmail.com> writes:
On Wednesday, 13 July 2022 at 01:23:35 UTC, D Lark wrote:
 First, please can someone clarify if the behaviour I expect in 
 the last line is consistent with the intention of the library?
Yes, it should behave the way you expect. The current behavior is a bug. I've submitted a report for it here: https://issues.dlang.org/show_bug.cgi?id=23242
Jul 12 2022
parent reply D Lark <dlark example.com> writes:
On Wednesday, 13 July 2022 at 01:40:43 UTC, Paul Backus wrote:
 On Wednesday, 13 July 2022 at 01:23:35 UTC, D Lark wrote:
 First, please can someone clarify if the behaviour I expect in 
 the last line is consistent with the intention of the library?
Yes, it should behave the way you expect. The current behavior is a bug. I've submitted a report for it here: https://issues.dlang.org/show_bug.cgi?id=23242
It looks like the resolution is that this can't be fixed? I'm not sure I understand the conclusion. What does this mean for this part of the library then? Should the RandomAccessInfinite!E interface be removed since it's not fully supported?
Jul 16 2022
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 16 July 2022 at 08:40:10 UTC, D Lark wrote:
 On Wednesday, 13 July 2022 at 01:40:43 UTC, Paul Backus wrote:
 On Wednesday, 13 July 2022 at 01:23:35 UTC, D Lark wrote:
 First, please can someone clarify if the behaviour I expect 
 in the last line is consistent with the intention of the 
 library?
Yes, it should behave the way you expect. The current behavior is a bug. I've submitted a report for it here: https://issues.dlang.org/show_bug.cgi?id=23242
It looks like the resolution is that this can't be fixed? I'm not sure I understand the conclusion. What does this mean for this part of the library then? Should the RandomAccessInfinite!E interface be removed since it's not fully supported?
The interface works fine, it's just that the `InputRangeObject!R` instance itself does not satisfy `isRandomAccessRange`: ```d auto seqObj = sequence!((a, n) => n).inputRangeObject; RandomAccessInfinite!size_t seqIface = seqObj; static assert( isRandomAccessRange!(typeof(seqIface))); // interface passes static assert(!isRandomAccessRange!(typeof(seqObj))); // object fails ``` So if you code to the interfaces and ignore the concrete type of the range object, you should not have any problems.
Jul 16 2022
parent D Lark <dlark example.com> writes:
On Saturday, 16 July 2022 at 12:40:09 UTC, Paul Backus wrote:
 On Saturday, 16 July 2022 at 08:40:10 UTC, D Lark wrote:
 On Wednesday, 13 July 2022 at 01:40:43 UTC, Paul Backus wrote:
 On Wednesday, 13 July 2022 at 01:23:35 UTC, D Lark wrote:
 [...]
Yes, it should behave the way you expect. The current behavior is a bug. I've submitted a report for it here: https://issues.dlang.org/show_bug.cgi?id=23242
It looks like the resolution is that this can't be fixed? I'm not sure I understand the conclusion. What does this mean for this part of the library then? Should the RandomAccessInfinite!E interface be removed since it's not fully supported?
The interface works fine, it's just that the `InputRangeObject!R` instance itself does not satisfy `isRandomAccessRange`: ```d auto seqObj = sequence!((a, n) => n).inputRangeObject; RandomAccessInfinite!size_t seqIface = seqObj; static assert( isRandomAccessRange!(typeof(seqIface))); // interface passes static assert(!isRandomAccessRange!(typeof(seqObj))); // object fails ``` So if you code to the interfaces and ignore the concrete type of the range object, you should not have any problems.
Thanks this definitely alleviates the issue somewhat. However it is definitely surprising that an object which literally derives from an interface cannot be tested to implement said interface. Is this inconsistency not a problem?
Jul 16 2022
prev sibling parent D Lark <dlark example.com> writes:
On Saturday, 16 July 2022 at 08:40:10 UTC, D Lark wrote:
 On Wednesday, 13 July 2022 at 01:40:43 UTC, Paul Backus wrote:
 On Wednesday, 13 July 2022 at 01:23:35 UTC, D Lark wrote:
 First, please can someone clarify if the behaviour I expect 
 in the last line is consistent with the intention of the 
 library?
Yes, it should behave the way you expect. The current behavior is a bug. I've submitted a report for it here: https://issues.dlang.org/show_bug.cgi?id=23242
It looks like the resolution is that this can't be fixed? I'm not sure I understand the conclusion. What does this mean for this part of the library then? Should the RandomAccessInfinite!E interface be removed since it's not fully supported?
What if infinite-ness is a class/struct level property distinct from empty-ness like `const enum bool infinite`? It appears to me that this is what we try to achieve by the unfortunate coupling of declaring `empty` as a manifest constant to denote an infinite range. If we have a distinct convention for declaring infiniteness then for the infinite range case we can insert `bool empty(){return false;}` (or `const enum bool = false)` automatically or check agreement. We can even have a mixin like the `ImplementLength` one that can add both `infinite` and `empty` in one go, which might be useful for implementing infinite ranges.
Jul 16 2022