A little challenge...

Robert Jacques sandford at jhu.edu
Sat Feb 27 11:30:18 PST 2010

On Sat, 27 Feb 2010 04:56:00 -0500, Norbert Nemec  
<Norbert at nemec-online.de> wrote:

> Robert Jacques wrote:
>> That sounds sensible. However, extensive experience in Matlab has  
>> taught me that resorting to custom for-loop indicates you've failed to  
>> sufficiently think in arrays. :)
> Indeed, most use cases are simple enough to be handled in array  
> notation. I have worked with Matlab and Python and managed to come up  
> with array notations in many non-trivial cases as well. However, once in  
> a while, it just cannot be done. Typically, this happens when you have  
> to handle non-linear terms or high order tensorial objects.
> Of course, my examples were simple enough to permit alternative  
> expressions, but I have encountered quite a number of cases where
> I could not avoid a loop in Python. I is hard to spontaneously construct  
> something useful that I can describe in a few lines.
> Imagine a charge density in one dimension:
> 	rho[r]
> and then compute the coulomb energy
> 	sum(r1,r2)(rho[r1]*rho[r2]/(r1-r2))
> Or an expression containing function calls
> 	sum(i,j)(f(i)*g(j)*A[i,j]))
> Ultimately, 'sum' and other reduction would actually be just one use  
> case. One could even use the same mechanism to construct arrays from  
> expressions.
> 	auto A = array(a=0:10,b=0:20)(2*a + b%3)
> (Disregard the exact syntax here...)
> I will think further about this and try to come up with more specific  
> use cases.
> Greetings,
> Norbert

Thank you. I understand the difficulty of finding good examples.  I did  
take a look at my own research, but didn't find any good examples of  
complex, single line expressions. Somehow, this feels like a narrow  
problem area; simple things are easy to express using array ops, really  
complex things take multiple lines to express and should really be done  
with loops in the first place. Finding the middle ground and then finding  
a concise way of correctly expressing it both seem like difficult  
problems, though definitely ones worth investigating. Anyways, I've taken  
a look at the new examples:

Let Map create an infinite array whose elements are generated via function  
calls. (I've run into the function call issue before)
Let Index = Map!"a" or something similar
Let .B!D denote broadcasting an array along the D dimension
Let .* denote the element wise multiply. Practically, you might want to  
use .A and .M to switch between element-wise array and matrix style math.
Practically, both Map and .B require the concept of one or more dimensions  
which are 'unbounded'. Unbounded dimensions become bounded when they  
interact with any operation that does bounds checking with a bounded  

sum(r1,r2)(rho[r1]*rho[r2]/(r1-r2))      => sum( rho.B!1.*rho.B!0./(  
Index.B!1 - Index.B!0 ) )
sum(i,j)(f(i)*g(j)*A[i,j]))              => sum( Map!f.B!1.*Map!g.B!0.*A )
auto A = array(a=0:10,b=0:20)(2*a + b%3) => auto A = take([0,10],[0,20],  
2*Index.B!1 + Index.B!0 % 3 );
                                             auto A = take( Map!"2*a +  
b%3"[0..10,0..20] )

Although the ideal syntax is definitely shorter and a bit more readable  
than the array ops version, the array ops seems more concise than the  
delegate based alternative:

sum( Map!((int i, int j){ return rho(i)*rho(j)/(i-j);  
})[0..rho.length,0..rho.length] );

By the way, I'd recommend keeping all these examples for use in your  
documentation, as people don't naturally think in arrays and array ops.

More information about the Digitalmars-d mailing list