Using Java Arrays

[The following description only applies to Kawa in CVS or 1.8.1 or newer. If you're using an older Kawa, skip to the last sub-section.]

Creating new Java arrays

To allocate a Java array you can use the make function. For example, you allocate an array with room for 10 elements each of each is a primitive int you can do this:

(make <int[]> length: 10)

If you use the type “expression” <int[]> as a function, you can leave out the make name, so this is equivalent:

(<int[]> length: 10)

You can specify the initial elements instead of the length:

(<object[]> 31 32 33 34)

This creates a 4-length array, initialized to the given values.

If you specify a length, you can also specify initial values for selected elements. If you specify an index, in the form of a literal integer-valued keyword, then following elements are placed starting at that position.

(<int[]> length: 100 10 12 80: 15 16 50: 13 14)

This creates an array with 100 elements. Most of them are initialized to the default value of zero, but elements with indexes 0, 1, 50, 51, 80, 81 are initialized to the values 10, 12, 13, 14, 15, 16, respectively.

Accessing Java array elements

You can access the elements of a Java array by treating it as a one-argument function, where the argument is the index:

(define primes (<integer[]> 2 3 5 7 11 13))
(primes 0) ==> 2
(primes 5) ==> 13

You can set an element by treating the array as a function with a setter:

(set! (primes 0) -2)
(set! (primes 3) -7)
primes ==> [-2 3 5 -7 11 13]

To get the number of elements of an array, you can treat it as having a length field:

primes:length ==> 6

Here is a longer example. This is the actual definition of the standard gcd function. Note the args variable receives all the arguments on the form of an Object array.

(define (gcd #!rest (args :: <Object[]>)) :: <integer>
  (let ((n :: <int> args:length))
    (if (zero? n)
	0
	(let ((result :: <integer> (args 0)))
	  (do ((i :: <int> 1 (+ i 1)))
	      ((>= i n) result)
	    (set! result (<integer>:gcd result (<integer>: (args i)))))))))

The above example generates good code, thanks to judicious use of casts and type specifications. In general, if Kawa knows that a “function” is an array then it will generate efficient bytecode instructions for array operations.

Old low-level array macros

[The following macros are deprecated in CVS, but you still have to use them in Kawa 1.8 or older.]

The following macros evaluate to procedures that can be used to manipulate primitive Java array objects. The compiler can inline each to a single bytecode instruction (not counting type conversion).

Syntax: primitive-array-new element-type

Evaluates to a one-argument procedure. Applying the resulting procedure to an integer count allocates a new Java array of the specified length, and whose elements have type element-type.

Syntax: primitive-array-set element-type

Evaluates to a three-argument procedure. The first argument of the resulting procedure must be an array whose elements have type element-type; the second argument is an index; and the third argument is a value (coercible to element-type) which replaces the value specified by the index in the given array.

Syntax: primitive-array-get element-type

Evaluates to a two-argument procedure. The first argument of the resulting procedure must be an array whose elements have type element-type; the second argument is an index. Applying the procedure returns the element at the specified index.

Syntax: primitive-array-length element-type

Evaluates to a one-argument procedure. The argument of the resulting procedure must be an array whose elements have type element-type. Applying the procedure returns the length of the array. (Alternatively, you can use (field array 'length).)