A little challenge...
Philippe Sigaud
philippe.sigaud at gmail.com
Fri Feb 26 12:17:14 PST 2010
On Fri, Feb 26, 2010 at 10:07, Norbert Nemec <Norbert at nemec-online.de>wrote:
> Jason House wrote:
>
>> Would sum!( "i", "a[i]*b[i]" ) be acceptable? That should be achievable
>> with a template mixin that does string mixins under the hood.
>>
>
> It is indeed a solution for the problem, but I still don't like it too
> much. For one, writing expressions as strings always feels awkward. Even
> though D can handle these strings at compile time, it just doesn't feel like
> writing native D code.
>
> Beyond this "gut feeling" I also see two technical problems:
>
> * code editors do not recognize the string content as code, so they cannot
> offer syntax highlighting or more advanced language tools
>
> * the syntax does not allow nesting:
>
> sum(i)( a[i] * sum(j)(b[i,j]*c[j]) )
>
You could use anonymous functions, like this:
sum!( (i,a,b) { return a[i]+b[i];})(array1, array2);
Here I consider a function of an index and some arrays, but you could use
functions on elements:
sum!( (a,b) { return a+b*a;})(array1, array2);
Editors can recognize these functions and they nest (though it's a bit
heavy):
sum!( (a,b) { return a + sum!((b) { return b*b;})(array2) * a)(array1);
A possible implementation for one array can be :
T sum(alias op, T)(T[] array) /* also, RandomAccessRange*/
{
T result;
foreach(i, elem; array) result += op(i, array);
return result;
}
It's quite simplified: I consider op returns a T...
Now, what's interesting is generalizing it somewhat : any number of inputs,
and inputs can be input ranges and not only arrays:
auto sum(alias op, R...)(R ranges) if(allSatisfy!(isInputRange,R))
{
alias staticMap!(ElementType,R) FrontType;
FrontType f;
typeof(op(f)) theSum;
while(!ranges[0].empty)
{
foreach(i, Type; FrontType) { // extracting the fronts
f[i] = ranges[i].front;
ranges[i].popFront;
}
theSum += op(f);
}
return theSum;
}
usage:
int[] ar1 = [0,1,2,3];
int[] ar2 = [4,5,6,7];
auto s = sum!((a,b,c) {return a+b*c;})(ar1,ar2,ar1);
writeln(s); // 44
Note that we could sum ranges with any element type, as long as the .init
value can be summed. float/double being initialiazed to NaN, it's a bit
tricky.
We could adopt std.algorithm 'string functions' trick, to get this syntax,
which I quite like:
auto s = sum!"a+b*c"(ar1, ar2, ar3);
Maybe you could be interested by looking at some modules with these ideas
at:
http://www.dsource.org/projects/dranges
(addendum: another generalization is of course to have two operations: the
'mapping' operation and the 'reducing' operation
like this:
auto sum = mapReduce!("a*b*c+1", "a+b")(range1, range2, range3);
The first function is applied on the elements, the second on the successive
results of the first fun.
Philippe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20100226/965dc544/attachment.html>
More information about the Digitalmars-d
mailing list