Next: , Up: Control features   [Contents][Index]

9.1 Mapping functions

The procedures `string-for-each` and `string-map` are documented under Strings.

The procedure `string-cursor-for-each` is documented under String Cursor API.

Procedure: map proc sequence1 sequence2 ...
Procedure: for-each proc sequence1 sequence2 ...

The `map` procedure applies proc element-wise to the elements of the sequences and returns a list of the results, in order. The dynamic order in which proc is applied to the elements of the sequences is unspecified.

The `for-each` procedure does the same, but is executed for the side-effects of proc, whose result (if any) is discarded. Unlike `map`, `for-each` is guaranteed to call proc on the elements of the sequencess in order from the first element(s) to the last. The value returned by `for-each` is the void value.

Each sequence must be a generalized sequence. (Traditionally, these arguments were restricted to lists, but Kawa allows sequences, including vectors, Java arrays, and strings.) If more than one sequence is given and not all sequences have the same length, the procedure terminates when the shortest sequence runs out. The sequences can be infinite (for example circular lists), but it is an error if all of them are infinite.

The proc must be a procedure that accepts as many arguments as there are sequence arguments. It is an error for proc to mutate any of the sequences. In the case of `map`, proc must return a single value.

```(map cadr '((a b) (d e) (g h)))
⇒ (b e h)

(map (lambda (n) (expt n n))
'(1 2 3 4 5))
⇒ (1 4 27 256 3125)

(map + ’(1 2 3) ’(4 5 6 7))  ⇒ (5 7 9)

(let ((count 0))
(map (lambda (ignored)
(set! count (+ count 1))
count)
'(a b)))
⇒ (1 2) or (2 1)
```

The result of `map` is a list, even if the arguments are non-lists:

```(map +
#(3 4 5)
(float[] 0.5 1.5))
⇒ (3.5 5.5)
```

To get a vector result, use `vector-map`.

```(let ((v (make-vector 5)))
(for-each (lambda (i)
(vector-set! v i (* i i)))
'(0 1 2 3 4))
v)
⇒  #(0 1 4 9 16)
```

A string is considered a sequence of `character` values (not 16-bit `char` values):

```(let ((v (make-vector 10 #\-)))
(for-each (lambda (i ch)
(vector-set! v i ch))
[0 <: ]
"Smile 😃!")
v)
⇒ #(#\S #\m #\i #\l #\e #\space #\x1f603 #\! #\- #\-)
```

Performance note: These procedures are pretty well optimized. For each sequence the compiler will by default create an iterator. However, if the type of the sequence is known, the compiler will inline the iteration code.

Procedure: vector-map proc sequence1 sequence2

Same as the `map` procedure, except the result is a vector. (Traditionally, these arguments were restricted to vectors, but Kawa allows sequences, including lists, Java arrays, and strings.)

```(vector-map cadr '#((a b) (d e) (g h)))
⇒ #(b e h)

(vector-map (lambda (n) (expt n n))
'#(1 2 3 4 5))
⇒ #(1 4 27 256 3125)

(vector-map + '#(1 2 3) ’#(4 5 6 7))
⇒ #(5 7 9)

(let ((count 0))
(vector-map
(lambda (ignored)
(set! count (+ count 1))
count)
'#(a b)))
⇒ #(1 2) or #(2 1)
```
Procedure: vector-for-each proc vector1 vector2

Mostly the same as `for-each`, however the arguments should be generalized vectors. Specifically, they should implement `java.util.List` (which both regular vectors and uniform vectors do). The vectors should also be efficiently indexable.

(Traditionally, these arguments were restricted to vectors, but Kawa allows sequences, including lists, Java arrays, and strings.)

```(let ((v (make-list 5)))
(vector-for-each
(lambda (i) (list-set! v i (* i i)))
'#(0 1 2 3 4))
v)
⇒ (0 1 4 9 16)
```

Next: , Up: Control features   [Contents][Index]