new to stackoverflow and new to racket. I've been studying racket using this documentation: https://docs.racket-lang.org/reference/pairs.html
This is my understanding of map:
(map (lambda (number) (+ 1 number))'(1 2 3 4))
this assigns '(1 2 3 4)
to variable number
,then map performs (+ 1 '(1 2 3 4))
.
but when I see things like:
(define (matrix_addition matrix_a matrix_b)
(map (lambda (x y) (map + x y)) matrix_a matrix_b))
I get very lost. I assume we're assigning two variables x
and y
, then performing (map + x y)
,but I don't understand what or how (map + x y)
works.
Another one I'm having trouble with is
(define (matrix_transpose matrix_a)
(apply map (lambda x x) matrix_a))
what does (lambda x x)
exactly do?
Thank you so much for clarifying. As you can see I've been working on matrix operations as suggested by a friend of mine.
Here is one way to think about map
:
(map f (list 1 2 3))
; computes
(list (f 1) (f 2) (f 3))
and
(map f (list 1 2 3) (list 11 22 33))
; computes
(list (f 1 11) (f 2 22) (f 3 33))
So your example with +
becomes:
(map + (list 1 2 3) (list 11 22 33))
; computes
(list (+ 1 11) (+ 2 22) (+ 3 33))
which is (list 12 24 36)
.
In the beginning it with be clearer to write
(define f (lambda (x y) (+ x y)))
(map f (list 1 2 3) (list 11 22 33)))
but when you can get used to map
and lambda
, the shorthand
(map (lambda (x y) (+ x y)) (list 1 2 3) (list 11 22 33)))
is useful.
this assigns
'(1 2 3 4)
to variablenumber
,thenmap
performs(+ 1 '(1 2 3 4))
.
No, that's not what it does. map
is a looping function, it calls the function separately for each element in the list, and returns a list of the results.
So first it binds number
to 1
and performs (+ 1 number)
, which is (+ 1 1)
. Then it binds number
to 2
and performs (+ 1 number)
, which is (+ 1 2)
. And so on. All the results are collected into a list, so it returns (2 3 4 5)
.
Getting to your matrix operation, the matrix is represented as a list of lists, so we need nested loops, which are done using nested calls to map
.
(map (lambda (x y) (map + x y)) matrix_a matrix_b)
The outer map
works as follows: First it binds x
and y
to the first elements of matrix_a
and matrix_b
respectively, and performs (map + x y)
. Then it binds x
and y
to the second elements of matrix_a
and matrix_b
, and performs (map + x y)
. And so on for each element of the two lists. Finally it returns a list of all these results.
The inner (map + x y)
adds the corresponding elements of the two lists, returning a list of the sums. E.g. (map + '(1 2 3) '(4 5 6))
returns (5 7 9)
.
So all together this creates a list of lists, where each element is the sum of the corresponding elements of matrix_a
and matrix_b
.
Finally,
what does
(lambda x x)
exactly do?
It binds x
to the list of all the arguments, and returns that list. So ((lambda x x) 1 2 3 4)
returns the list (1 2 3 4)
. It's basically the inverse of apply
, which spreads a list into multiple arguments to a function.
(apply (lambda x x) some-list)
returns a copy of some-list
.
this assigns '(1 2 3 4) to variable number ,then map performs (+ 1 '(1 2 3 4)).
If it was that simple why the need for map
. You could just do (+ 1 '(1 2 3 4))
directly. Here is an implementation of map1
which is map
that can only have one list argument:
(define (map1 fn lst)
(if (empty? lst)
empty
(cons (fn (first lst))
(map1 f (rest lst)))))
And what it does:
(map1 add1 '(1 2 3))
; ==> (cons (add1 1) (cons (add1 2) (cons (add1 3) empty)))
; same as (list (add1 1) (add1 2) (add1 3))
The real map
accepts any number of list arguments and then expect the element function to take as many elements that there are list arguments. eg.
(map (lambda (l n s) (list l n s)) '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
A very cool way to do this without knowing the number of elements is unzip
(define (unzip . lst)
(apply map list lst))
(unzip '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
So apply
flattens the call to (map list '(a b c) '(1 2 3) '($ % *))
and list
takes arbitrary elements so it ends up working the same way as th eprevious example, but it will also work for other dimentions:
(unzip '(a b c d) '(1 2 3 4))
; ==> ((a 1) (b 2) (c 3) (d 4))
The first argument of map
is a function. This function can require one or more arguments. Followed by the function in the arguments lists are one or more lists.
map
loops from first to the last element of the lists in parallel.
And feeds therefore the i-th position of each list as arguments to the function
and collects the result into a results list which it returns.
Now three short examples which would make it clear to you how map goes through the lists:
(map list '(1 2 3))
;; => '((1) (2) (3))
(map list '(1 2 3) '(a b c))
;; => '((1 a) (2 b) (3 c))
(map list '(1 2 3) '(a b c) '(A B C))
;; => '((1 a A) (2 b B) (3 c C))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With