matrixschemeracketapplytranspose# Matrix multiplication in scheme, List of lists

I started to study Scheme and I do not understand some of it. I'm using DrRacket.

I wrote the following code:

```
(define mult_mat
(λ (A B)
(Trans_Mat (map (λ (x) (mul_Mat_vec A x))
(Trans_Mat B)))))
```

That uses this functions:

```
(define Trans_Mat
(λ (A)
(apply map (cons list A))))
```

```
(define mul_Mat_vec
(λ (A v)
(map (λ (x) (apply + (map * x v)))
A)))
```

In `mult_mat`

, I multiply the matrix A in each vector of the transpose matrix B.
It works fine.

I found a code on the web that makes the multiplication in a way that I don't understand:

```
(define (matrix-multiply matrix1 matrix2)
(map
(λ (row)
(apply map
(λ column
(apply + (map * row column)))
matrix2))
matrix1))
```

In this code, `row`

is a list of the lists of matrix A, but I don't understand how the `column`

updates.

This part of the code: `(apply + (map * row column))`

is the dot product of vector `row`

and vector `column`

For example: A is a matrix 2X3 and B is a matrix 3X2 and if instead of `(apply + (map * row column))`

I write `1`

, then I'll get a matrix 2X2 with entries valued `1`

I don't understand how it works.

Thanks.

Solution

Ah, the old `( apply map foo _a_list_ )`

trick. Very clever.

In fact `(apply map (cons list A))`

is the same as `(apply map list A)`

. That's just how `apply`

is defined to work.

Trying out some concrete examples usually helps to "get it":

```
(apply map list '((1 2 3) (10 20 30)) )
=
(apply map (cons list '((1 2 3) (10 20 30))))
=
(apply map (list list '(1 2 3) '(10 20 30) ))
=
( map list '(1 2 3) '(10 20 30) )
=
'((1 10) (2 20) (3 30))
```

so that the elements of the last argument, `'((1 2 3) (10 20 30))`

, are *spliced in* into the whole`apply map ...`

form.

*Matrix transposition...* (list of lists, really).

So you have

```
(define (mult_mat A B)
(Trans_Mat (map (λ (B_column) (mul_Mat_vec A B_column))
(Trans_Mat B))))
(define (Trans_Mat A)
(apply map list A))
(define (mul_Mat_vec A v)
(map (λ (A_row) (apply + (map * A_row v)))
A))
(define (matrix-multiply A B)
(map
(λ (A_row)
(apply map
(λ B_column
(apply + (map * A_row B_column)))
B))
A))
```

Notice it's `(λ B_column ...`

, without parentheses. In `((λ args ...) x y z)`

, when the lambda is entered, `args`

gets all the arguments packaged in a list:

```
((λ args ...) x y z)
=
(let ([args (list x y z)])
...)
```

Also notice

```
(apply map
(λ B_column
(apply + (map * A_row B_column)))
B)
```

follows the same "tricky" pattern. It's in fact the same as

```
(apply map (cons
(λ B_column
(apply + (map * A_row B_column)))
B ) )
=
( map
(λ B_column
(apply + (map * A_row B_column)))
B_row1
B_row2
....
B_rowN )
=
(cons (let ([B_column_1 (map car B)])
(apply + (map * A_row B_column_1)))
(map (λ B_column
(apply + (map * A_row B_column)))
(cdr B_row1)
(cdr B_row2)
....
(cdr B_rowN)) )
=
(cons
(apply (λ B_column (apply + (map * A_row B_column)))
(map car B))
(apply map
(λ B_column
(apply + (map * A_row B_column)))
(map cdr B)))
```

by the definition of `map`

.

Thus, by *applying* the `map`

, the matrix is "opened up" into the list of its elements *the rows*, and then when the multi-argument `map`

gets to work on these rows as its arguments, the lambda function gets applied to each row's subsequent numbers, in unison, correspondingly; thus achieving the same effect as the *explicit transposition* would. But now the added bonus is, we don't need to transpose the result back into the proper form, as we had to with the first version.

This *is* very clever, and nice.

So, armed with all this understanding, let's try re-reading the original code and see if we can see into it as it is as well.

```
(define (matrix-multiply matrix1 matrix2)
(map
(λ (row)
(apply map
(λ column ;; <<------ no parens!
(apply + (map * row column)))
matrix2))
matrix1))
```

This reads: for each `row`

in `matrix1`

, multi-arg `map`

a `lambda`

over `matrix2`

. `matrix2`

is itself also a list of rows; when we multi-arg-`map`

over the rows, the `lambda`

gets applied to each column in the rows in turn.

So, for each *row* in `matrix1`

, for each *column* in `matrix2`

, multiply that row and that column element-wise and sum the results; thus transforming each row into the list of these sums. This obviously works out only if the length of the row and the lengths of each of the columns are the same: if the "width" of the first matrix and the "height" of the second matrix are the same.

- (Google Sheets) How to find column 1 and row 1 values for a matrix of occurrences in which both are present in data
- How to plot the camera and image positions from camera calibration data?
- Where does the third dimension (as in 4x4x4) of tensor cores come from?
- Transposing a 2D-array in JavaScript
- Printing 2D array using recursion (C programming)
- Logical error in matrix calculation code in C. error suspected in scope of Arrays
- Find the number of unique nodes in a graph in Python
- Numpy - Declare a specific nx1 array
- vertical dimensions mismatch (1x2 vs 1x1)
- Moving elements in a list-of-lists in prolog
- Create an off diagonal / moving window matrix
- How to fill a matrix that receives vectors of different sizes in R?
- How to reshape a matrix?
- Recursive Matrix Transposition in python
- Sparse matrix multiplication using linked lists
- How do I implement a function that calls specific column names on a list of data frames in R? Error with lapply
- LAPACK zgemm op(A) dimension
- How to convert irregular connected regions in a 2D matrix into rectangles in iOS?
- How to find connected components in a matrix using Julia
- Binary matrix to image in octave
- Checking if a matrix is symmetric in Numpy
- Implementing Jenkins Traub algorithm with inverse Power Iteration
- Issue with Encryption Algorithm in C
- Matrix Shortest Path
- R: Find set of columns which contain most 1s in matrix of 0 and 1
- Select column header value for a column with the largest Sum - Matrix
- create the complete symmetric matrix by copying the lower triangular of a sparse matrix in triplet format
- R - How do I run a regression based on a correlation matrix rather than raw data?
- How to write out a column vector
- Sample from a matrix by rows