<br><br><div class="gmail_quote">On Fri, Feb 26, 2010 at 10:07, Norbert Nemec <span dir="ltr"><<a href="mailto:Norbert@nemec-online.de">Norbert@nemec-online.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="im">Jason House wrote:<br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Would sum!( "i", "a[i]*b[i]" ) be acceptable? That should be achievable with a template mixin that does string mixins under the hood.<br>
</blockquote>
<br></div>
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.<br>
<br>
Beyond this "gut feeling" I also see two technical problems:<br>
<br>
* code editors do not recognize the string content as code, so they cannot offer syntax highlighting or more advanced language tools<br>
<br>
* the syntax does not allow nesting:<br>
<br>
sum(i)( a[i] * sum(j)(b[i,j]*c[j]) )<br></blockquote><div><br>You could use anonymous functions, like this:<br><br>sum!( (i,a,b) { return a[i]+b[i];})(array1, array2);<br><br>Here I consider a function of an index and some arrays, but you could use functions on elements:<br>
<br>
sum!( (a,b) { return a+b*a;})(array1, array2);<br>
<br>Editors can recognize these functions and they nest (though it's a bit heavy):<br><br>sum!( (a,b) { return a + sum!((b) { return b*b;})(array2) * a)(array1);<br><br>A possible implementation for one array can be :<br>
<br>T sum(alias op, T)(T[] array) /* also, RandomAccessRange*/<br>{<br> T result;<br> foreach(i, elem; array) result += op(i, array);<br> return result;<br>}<br><br>It's quite simplified: I consider op returns a T...<br>
<br>Now, what's interesting is generalizing it somewhat : any number of inputs, and inputs can be input ranges and not only arrays:<br><br>auto sum(alias op, R...)(R ranges) if(allSatisfy!(isInputRange,R))<br>{<br> alias staticMap!(ElementType,R) FrontType;<br>
FrontType f;<br> typeof(op(f)) theSum;<br> while(!ranges[0].empty)<br> {<br> foreach(i, Type; FrontType) { // extracting the fronts<br> f[i] = ranges[i].front;<br> ranges[i].popFront;<br>
}<br> theSum += op(f);<br> }<br> return theSum;<br>}<br><br>usage:<br><br>int[] ar1 = [0,1,2,3];<br>int[] ar2 = [4,5,6,7];<br>auto s = sum!((a,b,c) {return a+b*c;})(ar1,ar2,ar1);<br>writeln(s); // 44<br>
<br>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.<br><br>We could adopt std.algorithm 'string functions' trick, to get this syntax, which I quite like:<br>
<br>auto s = sum!"a+b*c"(ar1, ar2, ar3);<br><br>Maybe you could be interested by looking at some modules with these ideas at:<br><a href="http://www.dsource.org/projects/dranges">http://www.dsource.org/projects/dranges</a><br>
<br>(addendum: another generalization is of course to have two operations: the 'mapping' operation and the 'reducing' operation<br>like this:<br>auto sum = mapReduce!("a*b*c+1", "a+b")(range1, range2, range3);<br>
The first function is applied on the elements, the second on the successive results of the first fun.<br><br>Philippe<br> <br><br><br><br></div></div>