This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: APL-style array indexing in Kawa - a sketch


On Aug 18, 2015, at 12:11 AM, Per Bothner <per@bothner.com> wrote:

> On 08/17/2015 08:37 PM, Jamison Hope wrote:
>> On Aug 17, 2015, at 6:47 PM, Per Bothner <per@bothner.com> wrote:
>> 
>>> We could define [<:] as a supported syntax (see $bracket-list$ in syntax.scm).
>>> It would be relative easy to define 0 as the default lower bound, but that
>>> doesn't quite do what you want.  We could define [<;] as a special magic value
>>> that gets coerced to a specific range depending on context.
>> 
>> Hmm can we pick something that won't confuse paredit mode?
> 
> I'm not familiar with paredit - but why would [<:] confuse it?

Oh that was supposed to be a colon.  OK nevermind then, [<:] sounds good.
[>:] might also be useful, such that (VEC [>:]) reverses the sequence.


>> (array-map (lambda (x) (* 2 x)) ARR) => a new array where each element
>> is doubled in value.
>> 
>> (array-map + ARR1 ARR2) => a new array representing the elementwise sum
>> of the elements of ARR1 and ARR2.
>> 
>> (I'm imagining that the array-map call wouldn't allocate a new data
>> buffer, but would just close over the supplied function and array(s),
>> lazily applying the function to array elements as needed.)
> 
> "Lazily" is confusing here.  I think array-map should eager, in the
> same way vector-map is.  What it should do:
> (1) Figure out the shape of the result.  (The same as the argument, if
> a single argument; otherwise they may be "broadcast" in the Racket sense.)
> (2) Allocate an Object[] buffer for the result whose length is the
> element-count of the shape.
> (3) Iterate of the shape (which is the same as iterating over the buffer);
> extract the corresponding argument array value using the same (or broadcast)
> indexes; call the function.
> 
> http://docs.racket-lang.org/math/array_pointwise.html
> 
> The Racket array functions is another place to look for inspiration.

Perhaps "map" is the wrong name to use.  My motivation for wanting it to
be lazy is to be able to compose these things without causing a bunch of
temporary buffers to get allocated needlessly.

For instance, suppose * is redefined such that (* ATOM SEQ) performs
(array-map (lambda (x) (* ATOM x)) SEQ), and - is redefined such that
(- SEQ1 SEQ2) performs (array-map - SEQ1 SEQ2).

Then suppose we have an assignment such as

(define x (array-copy (* alpha (- u v))))

where alpha is a number and u and v (and x) are sequences.  If array-map
is lazy, then the iteration only needs to happen a single time, with
each element (x i) being effectively evaluated as
(* alpha (- (u i) (v i))).  If array-map is eager, then the iteration
must happen three times, first for the subtraction, then for the
multiplication, and then for the copy, allocating data buffers each
time.

https://en.wikipedia.org/wiki/Expression_templates

Like I said, maybe this should be called something other than "map".
Although SRFI-42 called its thing stream-map, so there's precedent
for lazy mapping.

--
Jamison Hope
The PTR Group
www.theptrgroup.com




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]