Reputation: 455
Hi all I am new at learning Scheme and often have issues with making parallels between an imperative language and a functional language.
For example if I had had two arrays.
A = [1 2 3]
B = [4 5 6]
If I wanted to create a new array with the elements of A multiplied by each element in B I could simply do something like (pseudo-code):
for(int i = 0; i < A.length; i++)
for(int j = 0; j < B.length, j++)
arr.push(A[i]*B[j])
Which would give back:
arr = [4 5 6 8 10 12 12 15 18]
What would be some ways to approach this problem in a functional language?
Upvotes: 3
Views: 1760
Reputation: 236112
In Scheme, the most common data structure is the linked list. Unless you have to access elements by index, it's always preferred to use lists, as there are countless built-in procedures for handling lists, that make easy to implement most algorithms without ever using an index. Just remember that for efficient access by index, using a vector would be a better idea.
Having said that, and depending on the Scheme dialect that you're using, the solution can be as simple as this (in Racket, see the documentation):
(define a '(1 2 3))
(define b '(4 5 6))
(for*/list ([x a] [y b])
(* x y))
=> '(4 5 6 8 10 12 12 15 18)
Alternatively, using only standard Scheme:
(apply append
(map (lambda (x)
(map (lambda (y) (* x y))
b))
a))
Upvotes: 4
Reputation: 31145
In Scheme and Racket arrays (array: a data structure indexed by a natural number) is represented using vectors.
(define as (vector 1 2 3))
(define bs (vector 4 5 6))
To make a loop-inside-a-loop we will use a variant of for*
.
Plain for*
works like this:
(for* ([a as] [b bs])
(displayln (* a b))))
Here a
runs through the elements of the vector as
and b
runs through the elements in bs
. Since for*
is used, the b-loop runs inside the a-loop.
If for
is used instead the loops run in parallel (try it).
Now since we want to collect the element, we can use for*/vector
which stores the generated elements in a vector:
(for*/vector ([a as] [b bs])
(* a b)))
For efficiency reason, one can write:
(for*/vector ([a (in-vector as)] [b (in-vector bs)])
(* a b)))
This will generate sligthly more efficient code.
However
(for*/vector ([a as] [b bs])
(* a b)))
will also work if as
and bs
are lists.
Upvotes: 0