May 02, 2012
Is there a general function for transforming a range back to the original type? If not, would it be possible to create one?

-- 
/Jacob Carlborg
May 02, 2012
On 05/02/2012 05:01 PM, Jacob Carlborg wrote:
> Is there a general function for transforming a range back to the
> original type? If not, would it be possible to create one?
>

I believe std.array's array function does what you want.
-Matt
May 02, 2012
On Wednesday, May 02, 2012 23:01:21 Jacob Carlborg wrote:
> Is there a general function for transforming a range back to the original type? If not, would it be possible to create one?

You mean that if you have something like

auto range = getRangeFromSomewhere();
auto newRange = find(filter!func(range), value);

you want to transform newRange back to the same type as range?

I don't believe that that's possible in the general case. For example, take

Array!int a = getArrayFromSomewhere(0;
auto range = a[];
auto newRange = find(filter!"a < 7"(range), 2);

The type of a[] is specific to Array!int, cannot be created externally from it, and is tightly coupled with the container. What if the container held the values [1, 7, 2, 9, 42, 0, -2, 4]? newRange would end up having [2 , 0, -2 , 4], which doesn't correspond to any range of elements in the Array. So, how could you convert newRange to the same type as range? The best that you could do as far as I can tell would be to create a new Array!int, put those elements in it, and slice the container.

So, I don't see how you could really take an arbitrary range and convert it back to its original type. With a very specific set of types, you might be able to (e.g. take([1, 2, 4, 9], 3) could be converted back to int[] easily enough), but with all of the wrapping that goes on with ranges, even determining what type of range is being wrapped by another can't be done generically AFAIK, let alone getting the whole chain down to the original range, let alone somehow converting the wrapped range back to that type.

Take remove in std.container, for example. It will only take the container's range type or the result of take on the container's range type - and it had to special case take. And removing a range from a container would be classic example of where you need the original range type rather than a wrapper.

- Jonathan M Davis
May 02, 2012
Jacob Carlborg:
> Is there a general function for transforming a range back to the original type? If not, would it be possible to create one?

The newly redesigned containers in Scala language are often able to do this, but this has required the use of a very advanced static type system, that is currently not in D (maybe there are ways to implement it with D templates, but it will require work to implement).
Currently there is array.array() that turns the range into a dynamic array.

Probably some types/data structures will have a way to turn a lazy range into one of them.

Bye,
bearophile
May 03, 2012
On Wed, 02 May 2012 23:01:21 +0200, Jacob Carlborg <doob@me.com> wrote:

> Is there a general function for transforming a range back to the original type? If not, would it be possible to create one?

In addition to std.array.array, as others have pointed out,
there is also std.range.InputRangeObject.
May 03, 2012
On 2012-05-02 23:07, Matt Soucy wrote:
> On 05/02/2012 05:01 PM, Jacob Carlborg wrote:
>> Is there a general function for transforming a range back to the
>> original type? If not, would it be possible to create one?
>>
>
> I believe std.array's array function does what you want.
> -Matt

I was thinking of a generic function that works for all types of collections and not arrays.

-- 
/Jacob Carlborg
May 03, 2012
On 2012-05-02 23:40, Jonathan M Davis wrote:
> On Wednesday, May 02, 2012 23:01:21 Jacob Carlborg wrote:
>> Is there a general function for transforming a range back to the
>> original type? If not, would it be possible to create one?
>
> You mean that if you have something like
>
> auto range = getRangeFromSomewhere();
> auto newRange = find(filter!func(range), value);
>
> you want to transform newRange back to the same type as range?

No, I want to transform newRange back to a collection, the same type as the original collection. I was thinking something like this:

Collection c = new Collection();
c = c.filter!(x => x < 3).toCollection();

-- 
/Jacob Carlborg
May 03, 2012
On 2012-05-03 09:43, Simen Kjaeraas wrote:

> In addition to std.array.array, as others have pointed out,
> there is also std.range.InputRangeObject.

I'm not sure if I understand what InputRangeObject does. But I don't think it does what I want.

-- 
/Jacob Carlborg
May 03, 2012
On Thu, 03 May 2012 13:17:40 +0200, Jacob Carlborg <doob@me.com> wrote:

> On 2012-05-03 09:43, Simen Kjaeraas wrote:
>
>> In addition to std.array.array, as others have pointed out,
>> there is also std.range.InputRangeObject.
>
> I'm not sure if I understand what InputRangeObject does. But I don't think it does what I want.

It basically wraps a range in a class interface. This allows you to use
InputRangeObject!T instead of T[]. I've never used it, so I'm not sure
what it does or how it does it.
May 03, 2012
On 02/05/2012 22:01, Jacob Carlborg wrote:
> Is there a general function for transforming a range back to the original type? If not,
> would it be possible to create one?

To sum it up, it can't be done in the general case.  The range API doesn't know or care about the underlying data structure.  That's half the point of it.  The underlying data structure might not even exist.  An example is a range used as a file stream, a random number generator or to lazily generate a mathematical sequence.

Moreover, what would you want such a function to return if the range is:
- a file stream with a cache
- an array wrapper to loop infinitely through it?
- a concatenation of ranges that may be of different types?

Moreover, even if there were some "range with an underlying container" classification, it would be an extra burden on the writer of the range wrapper to implement this.

If you want to generate a range that views a container in a certain way, and then construct a container of the original type (or indeed any type) from that range, then create the container and then use a foreach loop on the range (or a .save of it, if you want to keep the range afterwards) to put the data into the container.

Stewart.
« First   ‹ Prev
1 2 3 4
Top | Discussion index | About this forum | D home