More powerful foreach statements
Oskar Linde
oskar.lindeREM at OVEgmail.com
Fri Jul 21 08:15:00 PDT 2006
Andrei Khropov wrote:
> Oskar Linde wrote:
>
>> Python style ranges:
>>
>> foreach(x; range(5))
>> ... x is 0,1,2,3,4
>> foreach(x; range(1, 6))
>> ... x is 1,2,3,4,5
>> foreach(x; range(1.5, 0, -0.25)) // bad idea to support doubles?
>> ... x is 1.5, 1.25, 1.0, 0.75, 0.5, 0.25
>
> Mmm, I would like slices to be first-class types and some synactic sugar:
>
> -------------------------------------------------------
> foreach(i; 0..5)
> ... i is 0,1,2,3,4
>
>
> slice a = 1..5;
> int[5] arr = 0..5; // same as [0,1,2,3,4]
>
> foreach(x; arr[a])
> ... x is arr[1], arr[2], ... arr[4]
> -------------------------------------------------------
>
> But it's for D 1.0+ I think.
Yes. A slice type would be extremely nice, and would also be needed to
support slicing of user defined multidimensional arrays.
I would love to see
opSlice(int start, int end)
replaced with:
opIndex(Range r);
which would allow multidimensional mixed indexing and slicing like:
arr[a..b, c, d..e, f..g, h, i];
via some template hackery. This could be implemented without breaking
existing code by only calling opIndex(Range r) if no opSlice exists, so
there is no rush to get this before D 1.0.
>> I've not found a good iterator design yet though. Only supporting foreach
>> style iteration is a bit too limited.
>>
>> I would also like array views to work as iterators and also support common
>> array operations without having to generate temporary arrays.
>
> Yes, this is a definitely needed functionality.
>
>> Currently:
>>
>> double pensionCosts = employees
>> .filter((Employee e) { return e.age >= 28; })
>> .map((Employee e) { return e.salary * 0.04; })
>> .sum();
>>
>> Will generate a temporary Employee[] array and a temporary double[] array.
>>
>> Using array views one could get around the temporaries:
>>
>> // give all employees over 55 a 3 % raise:
>>
>> employees.select((Employee e) { return e.age >= 55; })
>> .update((Employee e) { e.salary *= 1.03; });
>>
>> //(No temporaries created.)
>>
>> /Oskar
>
> Such things should naturally belong to DTL I think.
Yeah. It's a pity D is so UDT hostile.
> And I would also like to see type inference for delegate params by argument
> type in parameter declaration, e.g. :
>
> -------------------------------------------------------
> employees.select( (e) { return e.age >= 55; })
> .update( (e) { e.salary *= 1.03; });
> -------------------------------------------------------
>
> e is inferred to be Employee in both cases because select and update are
> declared as
> -------------------------------------------------------
> ... select( delegate bool(Employee e) )
> ... update( delegate void(Employee e) )
> -------------------------------------------------------
>
> if select is overloaded with different types then this would be ambiguous of
> course and we have to explicitly specify arg type.
Yes, This makes D's delegates very close to Ruby's:
{|e| e.salary = e.salary * 1.03 }.
Exactly the same process of type inference exists already with foreach:
foreach(x; myObj)
// typeof(x) is inferred from the argument type of myObj.opApply()
/Oskar
More information about the Digitalmars-d
mailing list