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 18:32, Jakob Ovrum wrote:

> After a quick look over the thread again, I still don't see any real
> examples of use cases from Jacob (I admit I could still be missing it...
> somewhere...).

I can't recall I ever had a use case where I wanted to do some operation 
on a collection and then transforming it to another type of collection. 
I just want to perform the operation, then get back a collection of the 
same type:

int[] a = [3, 4, 5, 6 ,7];
a = a.filter!(x => x < 6);

Since that's not possible with the way ranges are designed I was 
thinking if it at least would be possible to have a generic interface to 
get the a collection (of the same type) out of the range.

-- 
/Jacob Carlborg
May 04, 2012
Re: Transforming a range back to the original type?
On 2012-05-04 19:15, Jonathan M Davis wrote:
> On Friday, May 04, 2012 13:46:33 Jacob Carlborg wrote:
>> I give up. Apparently you don't think it's useful.
>
> If you can come up with an example/reason why it would actually be useful,
> then great. But I don't see why it would ever matter what the original
> container type really was.
>
> You need the original range type in cases like std.container's remove
> function, but then the range must _be_ the original range type from that exact
> container in order to work, and there's no way that you could turn a wrapped
> range into the proper range for that, since you'd have to create a new
> container, and then the resultant range would be for the wrong container. And
> that's the only situation that I can think of where it really matters what the
> original container type was. If you want to construct a new container out of a
> range, then great, but since it's a new container, I don't see how it matters
> what the original container was unless you intend to assign the result to the
> new container or somesuch, in which case, you would already have access to the
> type, because you'd have a variable to assign to.
>
> - Jonathan M Davis

I have no problem if there's a new collection. I'm saying of the same 
_type_, not the same _collection_. As I've said in other posts in this 
thread, I mostly just want to assign the result of a range operation 
back to the original variable. Preferably I would like to not have to 
call any extra functions or constructors but that's not how ranges work.

-- 
/Jacob Carlborg
May 04, 2012
Re: Transforming a range back to the original type?
On Friday, 4 May 2012 at 19:17:13 UTC, Steven Schveighoffer wrote:
> This one:
>
> Collection c = new Collection();
> c = c.filter!(x => x < 3).toCollection();
>
> filter isn't a property of c, it's a range-producing function.  
> So I only have to define filter once, as a range accepting, 
> range producing function.  And any container type, as long as 
> it can produce a range, can use this as a pseudo method (via 
> UFCS) to make a filtered copy of itself.
>
> -Steve

That's not a real example, that's pretty much the same example I 
provided below the part you quoted.
May 04, 2012
Re: Transforming a range back to the original type?
On Fri, 04 May 2012 16:05:25 -0400, Jakob Ovrum <jakobovrum@gmail.com>  
wrote:

> On Friday, 4 May 2012 at 19:17:13 UTC, Steven Schveighoffer wrote:
>> This one:
>>
>> Collection c = new Collection();
>> c = c.filter!(x => x < 3).toCollection();
>>
>> filter isn't a property of c, it's a range-producing function.  So I  
>> only have to define filter once, as a range accepting, range producing  
>> function.  And any container type, as long as it can produce a range,  
>> can use this as a pseudo method (via UFCS) to make a filtered copy of  
>> itself.
>>
>> -Steve
>
> That's not a real example, that's pretty much the same example I  
> provided below the part you quoted.

First, what would you consider a real example?

Second, there's an important piece of the use case that your sample lacks  
-- Jacob is rebinding the result back to the original item.

So for example, I could see code like this:

void displayResults(Container c)
{
  if(maxvalue)
     c = c.filter!(x => x < maxvalue).makeContainer!Container();

  // proceed to display elements from c
}

-Steve
May 04, 2012
Re: Transforming a range back to the original type?
On 2012-05-04 22:05, Jakob Ovrum wrote:
> On Friday, 4 May 2012 at 19:17:13 UTC, Steven Schveighoffer wrote:
>> This one:
>>
>> Collection c = new Collection();
>> c = c.filter!(x => x < 3).toCollection();
>>
>> filter isn't a property of c, it's a range-producing function. So I
>> only have to define filter once, as a range accepting, range producing
>> function. And any container type, as long as it can produce a range,
>> can use this as a pseudo method (via UFCS) to make a filtered copy of
>> itself.
>>
>> -Steve
>
> That's not a real example, that's pretty much the same example I
> provided below the part you quoted.

Real world example:

https://github.com/jacob-carlborg/dstep/blob/master/dstep/translator/Type.d#L52

I was going to use "until" at row 59, but I couldn't figure out how to 
transform the range back to a string.

-- 
/Jacob Carlborg
May 04, 2012
Re: Transforming a range back to the original type?
On Friday, May 04, 2012 16:37:23 Steven Schveighoffer wrote:
> On Fri, 04 May 2012 16:05:25 -0400, Jakob Ovrum <jakobovrum@gmail.com>
> 
> wrote:
> > On Friday, 4 May 2012 at 19:17:13 UTC, Steven Schveighoffer wrote:
> >> This one:
> >> 
> >> Collection c = new Collection();
> >> c = c.filter!(x => x < 3).toCollection();
> >> 
> >> filter isn't a property of c, it's a range-producing function. So I
> >> only have to define filter once, as a range accepting, range producing
> >> function. And any container type, as long as it can produce a range,
> >> can use this as a pseudo method (via UFCS) to make a filtered copy of
> >> itself.
> >> 
> >> -Steve
> > 
> > That's not a real example, that's pretty much the same example I
> > provided below the part you quoted.
> 
> First, what would you consider a real example?
> 
> Second, there's an important piece of the use case that your sample lacks
> -- Jacob is rebinding the result back to the original item.
> 
> So for example, I could see code like this:
> 
> void displayResults(Container c)
> {
> if(maxvalue)
> c = c.filter!(x => x < maxvalue).makeContainer!Container();
> 
> // proceed to display elements from c
> }

std.container has make, which should do essentially that. And since you have 
the original container, you know what its type is, so there's no need to query 
the range for the original container type. Something like this should work:

c = make!Container(filter!(x => x < maxvalue)(c));

If it doesn't, then make and/or the container needs to be improved so that it 
does.

- Jonathan M Davis
May 04, 2012
Re: Transforming a range back to the original type?
On Friday, May 04, 2012 21:24:05 Jacob Carlborg wrote:
> I have no problem if there's a new collection. I'm saying of the same
> _type_, not the same _collection_. As I've said in other posts in this
> thread, I mostly just want to assign the result of a range operation
> back to the original variable.

Well, if you have a variable to assign to, then you know the type already. You 
don't need to query the range. You just need a way to create an instance of 
that container from the range. If it's an array, then use std.array.array. If 
it's a string, you can use std.conv.to (so that you get a string rather than a 
dstring). If it's standard a container, then std.container.make should do the 
trick. If it's another type, then as long as the type's constructor takes a 
range, you can just use the constructor. In general, it should just be one 
function call.

> Preferably I would like to not have to
> call any extra functions or constructors but that's not how ranges work.

A filter function which returned the same container type as it was passed would 
be doing something pretty similar to creating a range with the elements that 
match the predicate and creating a container from that. It might be more 
efficient depending on exactly how it was done and what the compiler's able to 
optimize, but it would be far less flexible. Ranges serve as building blocks, 
allowing us to chain functions in way that would be _really_ ineffecient with 
containers (using just one function might end up being more efficient, but if 
every such function in a chain is creating a new container, it would get very 
inefficient very quickly). Ranges end up being far more powerful. Yes, you then 
have to worry about putting the range in a container if you really want a 
container, but it should only take one function call, so I would think that 
the flexibility that ranges buy you would be well worth that small annoyance.

- Jonathan M Davis
Next ›   Last »
1 2 3 4
Top | Discussion index | About this forum | D home