Ах, старый ( apply map foo _a_list_ )
трюк. Очень умно.
На самом деле (apply map (cons list A))
совпадает с (apply map list A)
. Вот как apply
определено для работы.
Испытание некоторых конкретных примеров обычно помогает "получить это":
(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))
Матрица транспонирования . (список списков, правда.)
Итак, у вас есть
(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))
Обратите внимание, что это (λ B_column ...
, без скобок. В ((λ args ...) x y z)
, когда вводится лямбда, args
получает все аргументы, упакованные в список:
((λ args ...) x y z)
=
(let ([args (list x y z)])
...)
Также обратите внимание
(apply map
(λ B_column
(apply + (map * A_row B_column)))
B)
следует той же "хитрой" схеме. Это на самом деле так же, как
(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)))
(map cdr B_row1)
(map cdr B_row2)
....
(map 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)))
по определению map
.
Таким образом, применяя map
, матрица «раскрывается» в списке своих строк, а затем, когда map
начинает работать с этими строками в качестве аргументов, лямбда функция применяется к последующим номерам каждой строки, соответственно, в унисон; таким образом, достигая того же эффекта, что и явное преобразование . Но теперь добавленный бонус заключается в том, что нам не нужно переводить результат обратно в правильную форму, как мы делаем с вашей первой версией.
Это очень умно и приятно.