January 24, 2015
On 24.01.15 18:02, Andrei Alexandrescu wrote:
> On 1/24/15 7:17 AM, zeljkog wrote:
>>
>> private struct FilterResult(alias predicate, Range)
>> {
>>      static if (is(predicate == struct))
>>          predicate pred;
>>      else
>>          alias pred = predicate;
>> ...
> 
> The problem is here - the creation of an empty object is unlikely to be of use to the caller. We should, however, support the case when the caller passes a stateful predicate into the call. -- Andrei

I think empty object could be useful, but perhaps there is better :)

Until now I concluded:
1. Resulting range must be output range. Right?
   I don't know is it considerable problem?
2. unaryFun can pass down struct (with opCall check?)
January 24, 2015
On 24.01.15 18:26, zeljkog wrote:
>
> Until now I concluded:
> 1. Resulting range must be output range. Right?
Should be input range.

January 24, 2015
On 1/24/15 9:34 AM, zeljkog wrote:
> On 24.01.15 18:26, zeljkog wrote:
>>
>> Until now I concluded:
>> 1. Resulting range must be output range. Right?
> Should be input range.

For filter it's a forward range if input is forward or better. -- Andrei

January 24, 2015
On 24.01.15 19:35, Andrei Alexandrescu wrote:
> On 1/24/15 9:34 AM, zeljkog wrote:
>> On 24.01.15 18:26, zeljkog wrote:
>>>
>>> Until now I concluded:
>>> 1. Resulting range must be output range. Right?
>> Should be input range.
>
> For filter it's a forward range if input is forward or better. -- Andrei
>

But here there is potential problem with shared state after save?

January 24, 2015
On 1/24/15 10:41 AM, zeljkog wrote:
> On 24.01.15 19:35, Andrei Alexandrescu wrote:
>> On 1/24/15 9:34 AM, zeljkog wrote:
>>> On 24.01.15 18:26, zeljkog wrote:
>>>>
>>>> Until now I concluded:
>>>> 1. Resulting range must be output range. Right?
>>> Should be input range.
>>
>> For filter it's a forward range if input is forward or better. -- Andrei
>>
>
> But here there is potential problem with shared state after save?

It's not a problem - save saves the state of the iteration, not the data being iterated. -- Andrei

January 24, 2015
On Sat, Jan 24, 2015 at 10:35:13AM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
> On 1/24/15 9:34 AM, zeljkog wrote:
> >On 24.01.15 18:26, zeljkog wrote:
> >>
> >>Until now I concluded:
> >>1. Resulting range must be output range. Right?
> >Should be input range.
> 
> For filter it's a forward range if input is forward or better. -- Andrei

Hmm. Couldn't filter be made bidirectional too, if the underlying range is also bidirectional? After all, filtering doesn't depend on the surrounding elements, so in theory you should be able to popBack as well.


T

-- 
"How are you doing?" "Doing what?"
January 24, 2015
On 1/24/15 11:00 AM, H. S. Teoh via Digitalmars-d wrote:
> On Sat, Jan 24, 2015 at 10:35:13AM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
>> On 1/24/15 9:34 AM, zeljkog wrote:
>>> On 24.01.15 18:26, zeljkog wrote:
>>>>
>>>> Until now I concluded:
>>>> 1. Resulting range must be output range. Right?
>>> Should be input range.
>>
>> For filter it's a forward range if input is forward or better. --
>> Andrei
>
> Hmm. Couldn't filter be made bidirectional too, if the underlying range
> is also bidirectional? After all, filtering doesn't depend on the
> surrounding elements, so in theory you should be able to popBack as
> well.

History: http://dlang.org/phobos/std_algorithm.html#.filterBidirectional

Andrei

January 24, 2015
On 24.01.15 19:47, Andrei Alexandrescu wrote:
>>
>> But here there is potential problem with shared state after save?
> 
> It's not a problem - save saves the state of the iteration, not the data being iterated. -- Andrei
> 

If you pass stateful object with opCall or closure it becomes part of "state of the iteration"?

Consider:

import std.stdio, std.algorithm;

struct Uniq{
     bool[int] c;
     bool opCall(int a){
         if (a in c)
             return false;
         else{
             c[a] = true;
             return true;
         }
     }
}

void main()
{
    Uniq a;
    auto arr = [1, 5, 5, 2, 1, 5, 6, 6];
    auto r = arr.filter!a;
    auto r1 = r.save();
    r.writeln;
    r1.writeln;
}

output:

[1, 2, 6]
[5]





January 24, 2015
On Sat, Jan 24, 2015 at 11:20:55AM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
> On 1/24/15 11:00 AM, H. S. Teoh via Digitalmars-d wrote:
> >On Sat, Jan 24, 2015 at 10:35:13AM -0800, Andrei Alexandrescu via Digitalmars-d wrote:
[...]
> >>For filter it's a forward range if input is forward or better. -- Andrei
> >
> >Hmm. Couldn't filter be made bidirectional too, if the underlying range is also bidirectional? After all, filtering doesn't depend on the surrounding elements, so in theory you should be able to popBack as well.
> 
> History: http://dlang.org/phobos/std_algorithm.html#.filterBidirectional
[...]

Ah, I should have known, since I do remember seeing this when splitting std.algorithm. I guess it didn't really register beyond "this function belongs in std.algorithm.iteration". :-P

It's kinda sad that we can't merge the two functions and make it so that the initial scanning of .back only happens lazily. I mean, in theory, this should be easy:

	struct Filter {
		R range;
		...
		@property auto back() {
			while (!range.empty && !pred(range.back))
				range.popBack();
			return range.back;
		}
		void popBack() {
			range.popBack();
		}
	}

But I remember there was a huge discussion over whether .front/.back/.empty should do any non-trivial work. The current implementation appears to be the consequence of shoehorning all work into popFront/popBack. But in my mind, these methods ought to be abstract, and the user shouldn't be able to see any difference in behaviour regardless of where the real work is actually done.


T

-- 
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird. -- D. Knuth
January 24, 2015
On Saturday, 24 January 2015 at 14:53:02 UTC, Andrei Alexandrescu
wrote:
> On 1/24/15 3:50 AM, Peter Alexander wrote:
>> On Friday, 23 January 2015 at 18:22:08 UTC, zeljkog wrote:
>>> On 23.01.15 19:13, Andrei Alexandrescu wrote:
>>>> On 1/23/15 10:05 AM, zeljkog wrote:
>>>>> On 23.01.15 18:48, H. S. Teoh via Digitalmars-d wrote:
>>>>>>
>>>>>> I think what he's trying to do is to call a function that returns a
>>>>>> delegate, and use that delegate to instantiate the filter template.
>>>>>> AFAIK I've never seen code like this before, and it looks like the
>>>>>> compiler isn't prepared to handle this.
>>>>>>
>>>>>
>>>>> Yes, I tried to use filter for unique, need closure.
>>>>> I think there are many applications for this pattern.
>>>>
>>>> Please post a complete snippet then. Thanks! -- Andrei
>>>>
>>>
>>> import std.stdio, std.algorithm;
>>>
>>> auto unique(){
>>>    bool[int] c;
>>>    return (int a){
>>>        if (a in c)
>>>            return false;
>>>        else{
>>>            c[a] = true;
>>>            return true;
>>>        }
>>>    };
>>> }
>>>
>>> void main()
>>> {
>>>    [1, 5, 5, 2, 1, 5, 6, 6].filter!(unique()).writeln;
>>> }
>>
>> auto f = unique();
>> [1, 5, 5, 2, 1, 5, 6, 6].filter!(f).writeln;  // [1, 5, 2, 6]
>>
>> Filter needs an alias, and you cannot alias an R-value (it has no symbol).
>
> Hmmm... we do allow rvalues sometimes (e.g. for strings). I think we could and should relax the rule to allow rvalues in this case, too. -- Andrei

I was wrong. R-values work, as long as they are compile time
constants. The problem here is that closures don't yet work in
CTFE (as the error says). Pulling it out as a local variable
works because the alias then binds to the symbol rather than the
value.
1 2 3 4 5
Next ›   Last »