Jump to page: 1 2
Thread overview
Polymorphic ranges?
May 01, 2011
Andrej Mitrovic
May 01, 2011
Dmitry Olshansky
May 01, 2011
Andrej Mitrovic
May 01, 2011
Dmitry Olshansky
May 01, 2011
Andrej Mitrovic
May 02, 2011
Ali Çehreli
May 02, 2011
Andrej Mitrovic
May 02, 2011
Andrej Mitrovic
May 01, 2011
Andrej Mitrovic
May 01, 2011
Andrej Mitrovic
May 01, 2011
Andrej Mitrovic
May 01, 2011
Dmitry Olshansky
May 01, 2011
Andrej Mitrovic
May 02, 2011
Ali Çehreli
May 02, 2011
Ali Çehreli
May 01, 2011
As an example I have a cyclic buffer (using std.range.Cycle) where I can set the lower and upper bounds of the buffer. I'd also like to enable a stepping mode, so I thought first about using std.range.Stride.

The code: http://codepad.org/TR7NDWTC

This line is commented out:
//~ buffer = stride(buffer, newStep);

Obviously I can't assign a Stride structure to a Cycle structure. Structures aren't polymorphic.

The idea was that the private _buffer could be traversed in different ways, and the Work structure would allow reconfiguration on how the public "buffer" walks through the private _buffer array, this would be done at runtime via function calls like "setStep" which changes the buffer type.

But this isn't possible since buffer can only be one type, since it's a structure.

So the question is, how can I use std.range and its various types  polymorphically, is that in any way possible?

From what I can tell std.range functions all return structs. I was hoping of being able to do something like:

class Work
{
    float[256] _buffer;
    InfiniteRange buffer;

    this() { buffer = new InfiniteRange(_buffer); }  // initialize

    void setStride()
    {
        buffer = new Stride(buffer);  // now buffer has a dynamic type of Stride, which would be a subtype of InfiniteRange
    }
}

And then main would create a Work object, and call its buffer.front and buffer.popFront properties, and later call setStride to change how the object behaves by simply creating a new subtype which has the same interface but different behavior.

But I can't do that here since pretty much everything in std.range returns a struct.
May 01, 2011
On 01.05.2011 6:33, Andrej Mitrovic wrote:
> As an example I have a cyclic buffer (using std.range.Cycle) where I can set the lower and upper bounds of the buffer. I'd also like to enable a stepping mode, so I thought first about using std.range.Stride.
>
> The code: http://codepad.org/TR7NDWTC
>
> This line is commented out:
> //~ buffer = stride(buffer, newStep);
>
> Obviously I can't assign a Stride structure to a Cycle structure. Structures aren't polymorphic.
>
> The idea was that the private _buffer could be traversed in different ways, and the Work structure would allow reconfiguration on how the public "buffer" walks through the private _buffer array, this would be done at runtime via function calls like "setStep" which changes the buffer type.
>
> But this isn't possible since buffer can only be one type, since it's a structure.
>
> So the question is, how can I use std.range and its various types  polymorphically, is that in any way possible?
>
>  From what I can tell std.range functions all return structs. I was hoping of being able to do something like:
>
> class Work
> {
>      float[256] _buffer;
>      InfiniteRange buffer;
>
>      this() { buffer = new InfiniteRange(_buffer); }  // initialize
>
>      void setStride()
>      {
>          buffer = new Stride(buffer);  // now buffer has a dynamic type of Stride, which would be a subtype of InfiniteRange
>      }
> }
>
> And then main would create a Work object, and call its buffer.front and buffer.popFront properties, and later call setStride to change how the object behaves by simply creating a new subtype which has the same interface but different behavior.
>
> But I can't do that here since pretty much everything in std.range returns a struct.
There is a polymorphic wrapper for any range in std.range, try inputRangeObject & outputRangeObject. Every such range object is derived from the most suitable interface InputRange, ForwardRange etc.

-- 
Dmitry Olshansky

May 01, 2011
I'm not sure how to use those wrappers though. Maybe I'm just doing it wrong:

http://codepad.org/eHIdhasc

But it seems these wrappers have some problems, the docs say about the interfaces:

Limitations:
These interfaces are not capable of forwarding ref access to elements.
Infiniteness of the wrapped range is not propagated.
Length is not propagated in the case of non-random access ranges.
May 01, 2011
On 01.05.2011 18:30, Andrej Mitrovic wrote:
> I'm not sure how to use those wrappers though. Maybe I'm just doing it wrong:
>
> http://codepad.org/eHIdhasc
>
> But it seems these wrappers have some problems, the docs say about the
> interfaces:
>
> Limitations:
> These interfaces are not capable of forwarding ref access to elements.
> Infiniteness of the wrapped range is not propagated.
> Length is not propagated in the case of non-random access ranges.
Well, this compiles, you just need to pick suitable type of range 'interface', that's the subtle thingie:
http://codepad.org/uE0nIwbk

Limitations are caused by bug, that is going to get fixed eventually ;)

-- 
Dmitry Olshansky

May 01, 2011
Yeah it seems a common interface is what I should have used. I've tried it in numerous ways but I got the interface type wrong apparently. Thanks Dmitry.

Here's a quick example:
http://codepad.org/RhNiUHU2

I hope those bugs get squashed so I can have more fun with these ranges. :)
May 01, 2011
Unfortunately as you can see I can't convert a Stride to a RandomAccessInfinite object, so I've had to use an InputRange interface (I can also use ForwardRange which is more derived). I'm not sure why I can't use it (maybe it's that bug again?), because Stride itself does offer random access.
May 01, 2011
Actually that design of mine was bad because it creates a long chain of virtual calls since setStep just wraps the buffer object and creates a new object every time.

Here's an alternate implementation: https://gist.github.com/950647
May 01, 2011
Btw,

 * Limitations:
 *
 * These interfaces are not capable of forwarding $(D ref) access to elements.

Why not? I can use auto ref to make e.g. an input range interface that can return ref elements:

http://codepad.org/kmenIDk7

Why aren't the interfaces defined like that in std.range?
May 01, 2011
On 01.05.2011 21:40, Andrej Mitrovic wrote:
> Btw,
>
>   * Limitations:
>   *
>   * These interfaces are not capable of forwarding $(D ref) access to elements.
>
> Why not? I can use auto ref to make e.g. an input range interface that
> can return ref elements:
>
> http://codepad.org/kmenIDk7
>
> Why aren't the interfaces defined like that in std.range?
One reason might be is that it was implemented under worse compiler condition ;)
Seems worthy of a bug report, or better yet a pull request.

-- 
Dmitry Olshansky

May 01, 2011
opSlice isn't supported either. Gah.., so much for this being useful. I'll have to roll my own.

Now I know why Tango was developed. <g>
« First   ‹ Prev
1 2