View mode: basic / threaded / horizontal-split · Log in · Help
May 04, 2012
Re: Transforming a range back to the original type?
On 2012-05-04 01:11, Stewart Gordon wrote:

> 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.

Yeah, I know, I know. It's all good in theory but I never found a use 
for it in practice and in most cases it's just annoying.

> 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?

I was mostly thinking when the range originated from a collection. Where 
it's actually possible to transfer the range back to the original 
collection type.

> 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.

No, I was thinking that the developer of the collection would provide 
that. I mean, it's already possible to transform a range to an array, 
I'm sure it's possible to transform it to a list of some kind as well. 
Then we could have this for example:

collA.range.toArray();
collB.range.toList();

What I was asking for was if there is, or could be, a generic interface 
for this. Something like:

collA.range.toCollection();
collA.range.toCollection();

If "collA" is an array "toCollection" would transform the range to an 
array, just as std.array.array does. If "collB" is a list the range 
would be transformed back in to a list.

> 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.


-- 
/Jacob Carlborg
May 04, 2012
Re: Transforming a range back to the original type?
On 2012-05-03 00:34, bearophile wrote:

> 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).

I've heard of that. I've started to read a paper about how the 
collection API is implemented.

-- 
/Jacob Carlborg
May 04, 2012
Re: Transforming a range back to the original type?
On Friday, May 04, 2012 08:32:09 Jacob Carlborg wrote:
> On 2012-05-04 01:11, Stewart Gordon wrote:
> > 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.
> 
> Yeah, I know, I know. It's all good in theory but I never found a use
> for it in practice and in most cases it's just annoying.
> 
> > 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?
> 
> I was mostly thinking when the range originated from a collection. Where
> it's actually possible to transfer the range back to the original
> collection type.
> 
> > 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.
> 
> No, I was thinking that the developer of the collection would provide
> that. I mean, it's already possible to transform a range to an array,
> I'm sure it's possible to transform it to a list of some kind as well.
> Then we could have this for example:
> 
> collA.range.toArray();
> collB.range.toList();
> 
> What I was asking for was if there is, or could be, a generic interface
> for this. Something like:
> 
> collA.range.toCollection();
> collA.range.toCollection();
> 
> If "collA" is an array "toCollection" would transform the range to an
> array, just as std.array.array does. If "collB" is a list the range
> would be transformed back in to a list.

Something like that could probably only be done if every range in the 
potentially large chain of wrapped ranges provided a means of getting at what 
type the previous one in the chain was, and very few ranges - if any - do 
that.

However, I'm not quite sure what toCollection would buy you. Why does it 
really matter what type of container the range comes from originally given 
that you have to create a new container to put the elements of the range into 
such a container? And if you're putting the elements of a range in a new 
container, you can pick whatever container type you'd like, and since it has 
no real connection to the original container, I don't see why it would matter 
whether it was the same type of container. All you really need is the 
equivalent of std.array.array for whatever container you want to construct, 
and the container's constructor should provide that.

- Jonathan M Davis
May 04, 2012
Re: Transforming a range back to the original type?
On 2012-05-04 09:01, Jonathan M Davis wrote:

> Something like that could probably only be done if every range in the
> potentially large chain of wrapped ranges provided a means of getting at what
> type the previous one in the chain was, and very few ranges - if any - do
> that.
>
> However, I'm not quite sure what toCollection would buy you. Why does it
> really matter what type of container the range comes from originally given
> that you have to create a new container to put the elements of the range into
> such a container? And if you're putting the elements of a range in a new
> container, you can pick whatever container type you'd like, and since it has
> no real connection to the original container, I don't see why it would matter
> whether it was the same type of container. All you really need is the
> equivalent of std.array.array for whatever container you want to construct,
> and the container's constructor should provide that.

It's just like with the whole range idea, providing a common interface 
for iterating over a collection (and some other stuff). Here the idea is 
to have a common interface to transform the range back to a collection.

-- 
/Jacob Carlborg
May 04, 2012
Re: Transforming a range back to the original type?
On Friday, May 04, 2012 11:20:58 Jacob Carlborg wrote:
> On 2012-05-04 09:01, Jonathan M Davis wrote:
> > Something like that could probably only be done if every range in the
> > potentially large chain of wrapped ranges provided a means of getting at
> > what type the previous one in the chain was, and very few ranges - if any
> > - do that.
> > 
> > However, I'm not quite sure what toCollection would buy you. Why does it
> > really matter what type of container the range comes from originally given
> > that you have to create a new container to put the elements of the range
> > into such a container? And if you're putting the elements of a range in a
> > new container, you can pick whatever container type you'd like, and since
> > it has no real connection to the original container, I don't see why it
> > would matter whether it was the same type of container. All you really
> > need is the equivalent of std.array.array for whatever container you want
> > to construct, and the container's constructor should provide that.
> 
> It's just like with the whole range idea, providing a common interface
> for iterating over a collection (and some other stuff). Here the idea is
> to have a common interface to transform the range back to a collection.

But what's special about the original container type? Once the range has been 
wrapped, it doesn't really have any connection to the container - particuarly 
when elements are likely to have been transformed and/or skipped or added such 
that they're no longer strongly linked with the original elements. As far as I 
can tell, the original container type becomes pretty much meaningless at that 
point.

You should be able to put the elements that are in the range in whatever 
container type you want (which you can currently do very easily with arrays 
thanks to std.array.array and should be able to do with std.container's 
containers with their constructors), so you can put them in whatever container 
type is appropriate for whatever you're going to do with the elements. But I 
don't see how the _original_ container type matters for any of that.

And when you consider that it's quite possible for a range to have no 
connection to a container whatsoever (e.g. anything in std.random), I just 
don't see how you could generically get at the type of the original container 
anyway (since there may not be one). Best case, you could create variable or 
alias which a range type _could_ have but doesn't necessarily have (similar to 
save or back) which could then hold the original container type (effectively 
creating yet another genre of range). But again, I don't see why that would 
actually be useful.

- Jonathan M Davis
May 04, 2012
Re: Transforming a range back to the original type?
On 2012-05-04 11:38, Jonathan M Davis wrote:
> On Friday, May 04, 2012 11:20:58 Jacob Carlborg wrote:
>> On 2012-05-04 09:01, Jonathan M Davis wrote:
>>> Something like that could probably only be done if every range in the
>>> potentially large chain of wrapped ranges provided a means of getting at
>>> what type the previous one in the chain was, and very few ranges - if any
>>> - do that.
>>>
>>> However, I'm not quite sure what toCollection would buy you. Why does it
>>> really matter what type of container the range comes from originally given
>>> that you have to create a new container to put the elements of the range
>>> into such a container? And if you're putting the elements of a range in a
>>> new container, you can pick whatever container type you'd like, and since
>>> it has no real connection to the original container, I don't see why it
>>> would matter whether it was the same type of container. All you really
>>> need is the equivalent of std.array.array for whatever container you want
>>> to construct, and the container's constructor should provide that.
>>
>> It's just like with the whole range idea, providing a common interface
>> for iterating over a collection (and some other stuff). Here the idea is
>> to have a common interface to transform the range back to a collection.
>
> But what's special about the original container type? Once the range has been
> wrapped, it doesn't really have any connection to the container - particuarly
> when elements are likely to have been transformed and/or skipped or added such
> that they're no longer strongly linked with the original elements. As far as I
> can tell, the original container type becomes pretty much meaningless at that
> point.

I give up. Apparently you don't think it's useful.

-- 
/Jacob Carlborg
May 04, 2012
Re: Transforming a range back to the original type?
On Friday, 4 May 2012 at 11:46:34 UTC, Jacob Carlborg wrote:
> I give up. Apparently you don't think it's useful.

I'm not seeing it either, but it might help if you gave a 
concrete example of where it could/should be used and what 
benefits it might have. I think it'll be rather hard to come up 
with an example where the programmer wouldn't know what the 
original type was and have it actually matter.
May 04, 2012
Re: Transforming a range back to the original type?
On Thu, 03 May 2012 04:41:50 -0400, Jacob Carlborg <doob@me.com> wrote:

> 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();

Why can't the last line be:

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

or more generically:

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

?

-Steve
May 04, 2012
Re: Transforming a range back to the original type?
On Friday, 4 May 2012 at 12:49:35 UTC, Steven Schveighoffer wrote:
> or more generically:
>
> c = new typeof(c)(c.filter!(x => x < 3));
>
> ?

That doesn't do the right thing when 'c' isn't a class type, so 
it's not really that generic.

Struct types (the type of `new typeof(c)` is not `typeof(c)`!) 
and array types simply fail with your suggestion.

I personally haven't decided whether I think a generic convention 
is useful here, but that code doesn't fit the bill.
May 04, 2012
Re: Transforming a range back to the original type?
On Fri, 04 May 2012 09:06:31 -0400, Jakob Ovrum <jakobovrum@gmail.com>  
wrote:

> On Friday, 4 May 2012 at 12:49:35 UTC, Steven Schveighoffer wrote:
>> or more generically:
>>
>> c = new typeof(c)(c.filter!(x => x < 3));
>>
>> ?
>
> That doesn't do the right thing when 'c' isn't a class type, so it's not  
> really that generic.
>
> Struct types (the type of `new typeof(c)` is not `typeof(c)`!) and array  
> types simply fail with your suggestion.

Structs don't make very good containers.  A slice is not really a  
container.

But in any case, someone can make a function that's generic with a couple  
static ifs.

> I personally haven't decided whether I think a generic convention is  
> useful here, but that code doesn't fit the bill.

What exactly are you looking for?  I mean, you want the original type  
back, so you can reassign, is that all?  Something like this should work  
for that:

c = makeContainer!typeof(c)(c.filter!(x => x < 3));

Implementation left as an exercise.

-Steve
1 2 3 4
Top | Discussion index | About this forum | D home