在 Racket 中寻找关于 'map' 的说明
Looking for clarification on 'map' in Racket
Whosebug 的新手和球拍的新手。我一直在使用此文档研究球拍:https://docs.racket-lang.org/reference/pairs.html
这是我对地图的理解:
(map (lambda (number) (+ 1 number))'(1 2 3 4))
这会将 '(1 2 3 4)
分配给变量 number
,然后 map 执行 (+ 1 '(1 2 3 4))
.
但是当我看到类似的东西时:
(define (matrix_addition matrix_a matrix_b)
(map (lambda (x y) (map + x y)) matrix_a matrix_b))
我迷路了。我假设我们正在分配两个变量 x
和 y
,然后执行 (map + x y)
,但我不明白 (map + x y)
是什么或如何工作。
我遇到的另一个问题是
(define (matrix_transpose matrix_a)
(apply map (lambda x x) matrix_a))
(lambda x x)
到底是做什么的?
非常感谢您的澄清。如您所见,我一直在按照我朋友的建议进行矩阵运算。
this assigns '(1 2 3 4)
to variable number
,then map
performs (+ 1 '(1 2 3 4))
.
不,这不是它的作用。 map
是一个循环函数,它为列表中的每个元素分别调用函数,returns一个结果列表。
所以首先它将number
绑定到1
并执行(+ 1 number)
,即(+ 1 1)
。然后它绑定number
到2
并执行(+ 1 number)
,即(+ 1 2)
。等等。所有的结果都收集到一个列表中,所以它 returns (2 3 4 5)
.
进入矩阵运算,矩阵表示为列表的列表,因此我们需要嵌套循环,这是使用对 map
.
的嵌套调用完成的
(map (lambda (x y) (map + x y)) matrix_a matrix_b)
外层map
的工作原理如下:首先将x
和y
分别绑定到matrix_a
和matrix_b
的第一个元素,然后执行(map + x y)
。然后将x
和y
绑定到matrix_a
和matrix_b
的第二个元素上,并执行(map + x y)
。对于两个列表的每个元素,依此类推。最后它 returns 所有这些结果的列表。
里面的(map + x y)
把两个列表对应的元素相加,返回求和的列表。例如。 (map + '(1 2 3) '(4 5 6))
returns (5 7 9)
.
所以所有这些一起创建了一个列表列表,其中每个元素都是 matrix_a
和 matrix_b
.
对应元素的总和
最后,
what does (lambda x x)
exactly do?
它将 x
绑定到所有参数的列表,并且 returns 该列表。所以 ((lambda x x) 1 2 3 4)
returns 列表 (1 2 3 4)
。它基本上是 apply
的反函数,它将一个列表扩展到一个函数的多个参数中。
(apply (lambda x x) some-list)
returns some-list
.
的副本
这是一种思考 map
的方法:
(map f (list 1 2 3))
; computes
(list (f 1) (f 2) (f 3))
和
(map f (list 1 2 3) (list 11 22 33))
; computes
(list (f 1 11) (f 2 22) (f 3 33))
所以您的 +
示例变为:
(map + (list 1 2 3) (list 11 22 33))
; computes
(list (+ 1 11) (+ 2 22) (+ 3 33))
也就是 (list 12 24 36)
.
开头写的比较清楚
(define f (lambda (x y) (+ x y)))
(map f (list 1 2 3) (list 11 22 33)))
但是当你习惯了map
和lambda
之后,shorthand
(map (lambda (x y) (+ x y)) (list 1 2 3) (list 11 22 33)))
有用。
this assigns '(1 2 3 4) to variable number ,then map performs (+ 1 '(1 2 3 4)).
如果就这么简单,为什么需要 map
。你可以直接做 (+ 1 '(1 2 3 4))
。这是 map1
的一种实现,即 map
只能有一个列表参数:
(define (map1 fn lst)
(if (empty? lst)
empty
(cons (fn (first lst))
(map1 f (rest lst)))))
它的作用:
(map1 add1 '(1 2 3))
; ==> (cons (add1 1) (cons (add1 2) (cons (add1 3) empty)))
; same as (list (add1 1) (add1 2) (add1 3))
真正的 map
接受任意数量的列表参数,然后期望元素函数采用与列表参数一样多的元素。例如
(map (lambda (l n s) (list l n s)) '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
在不知道元素数量的情况下执行此操作的一种非常酷的方法是 unzip
(define (unzip . lst)
(apply map list lst))
(unzip '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
所以 apply
将对 (map list '(a b c) '(1 2 3) '($ % *))
的调用展平,而 list
接受任意元素,因此它最终的工作方式与上一个示例相同,但它也适用于其他维度:
(unzip '(a b c d) '(1 2 3 4))
; ==> ((a 1) (b 2) (c 3) (d 4))
map
的第一个参数是一个函数。此函数可能需要一个或多个参数。参数列表中的函数后面是一个或多个列表。
map
从列表的第一个元素到最后一个元素并行循环。
因此将每个列表的第 i 个位置作为函数的参数
并将结果收集到结果列表中 returns.
现在三个简短的例子可以让你清楚地图是如何遍历列表的:
(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))
Whosebug 的新手和球拍的新手。我一直在使用此文档研究球拍:https://docs.racket-lang.org/reference/pairs.html
这是我对地图的理解:
(map (lambda (number) (+ 1 number))'(1 2 3 4))
这会将 '(1 2 3 4)
分配给变量 number
,然后 map 执行 (+ 1 '(1 2 3 4))
.
但是当我看到类似的东西时:
(define (matrix_addition matrix_a matrix_b)
(map (lambda (x y) (map + x y)) matrix_a matrix_b))
我迷路了。我假设我们正在分配两个变量 x
和 y
,然后执行 (map + x y)
,但我不明白 (map + x y)
是什么或如何工作。
我遇到的另一个问题是
(define (matrix_transpose matrix_a)
(apply map (lambda x x) matrix_a))
(lambda x x)
到底是做什么的?
非常感谢您的澄清。如您所见,我一直在按照我朋友的建议进行矩阵运算。
this assigns
'(1 2 3 4)
to variablenumber
,thenmap
performs(+ 1 '(1 2 3 4))
.
不,这不是它的作用。 map
是一个循环函数,它为列表中的每个元素分别调用函数,returns一个结果列表。
所以首先它将number
绑定到1
并执行(+ 1 number)
,即(+ 1 1)
。然后它绑定number
到2
并执行(+ 1 number)
,即(+ 1 2)
。等等。所有的结果都收集到一个列表中,所以它 returns (2 3 4 5)
.
进入矩阵运算,矩阵表示为列表的列表,因此我们需要嵌套循环,这是使用对 map
.
(map (lambda (x y) (map + x y)) matrix_a matrix_b)
外层map
的工作原理如下:首先将x
和y
分别绑定到matrix_a
和matrix_b
的第一个元素,然后执行(map + x y)
。然后将x
和y
绑定到matrix_a
和matrix_b
的第二个元素上,并执行(map + x y)
。对于两个列表的每个元素,依此类推。最后它 returns 所有这些结果的列表。
里面的(map + x y)
把两个列表对应的元素相加,返回求和的列表。例如。 (map + '(1 2 3) '(4 5 6))
returns (5 7 9)
.
所以所有这些一起创建了一个列表列表,其中每个元素都是 matrix_a
和 matrix_b
.
最后,
what does
(lambda x x)
exactly do?
它将 x
绑定到所有参数的列表,并且 returns 该列表。所以 ((lambda x x) 1 2 3 4)
returns 列表 (1 2 3 4)
。它基本上是 apply
的反函数,它将一个列表扩展到一个函数的多个参数中。
(apply (lambda x x) some-list)
returns some-list
.
这是一种思考 map
的方法:
(map f (list 1 2 3))
; computes
(list (f 1) (f 2) (f 3))
和
(map f (list 1 2 3) (list 11 22 33))
; computes
(list (f 1 11) (f 2 22) (f 3 33))
所以您的 +
示例变为:
(map + (list 1 2 3) (list 11 22 33))
; computes
(list (+ 1 11) (+ 2 22) (+ 3 33))
也就是 (list 12 24 36)
.
开头写的比较清楚
(define f (lambda (x y) (+ x y)))
(map f (list 1 2 3) (list 11 22 33)))
但是当你习惯了map
和lambda
之后,shorthand
(map (lambda (x y) (+ x y)) (list 1 2 3) (list 11 22 33)))
有用。
this assigns '(1 2 3 4) to variable number ,then map performs (+ 1 '(1 2 3 4)).
如果就这么简单,为什么需要 map
。你可以直接做 (+ 1 '(1 2 3 4))
。这是 map1
的一种实现,即 map
只能有一个列表参数:
(define (map1 fn lst)
(if (empty? lst)
empty
(cons (fn (first lst))
(map1 f (rest lst)))))
它的作用:
(map1 add1 '(1 2 3))
; ==> (cons (add1 1) (cons (add1 2) (cons (add1 3) empty)))
; same as (list (add1 1) (add1 2) (add1 3))
真正的 map
接受任意数量的列表参数,然后期望元素函数采用与列表参数一样多的元素。例如
(map (lambda (l n s) (list l n s)) '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
在不知道元素数量的情况下执行此操作的一种非常酷的方法是 unzip
(define (unzip . lst)
(apply map list lst))
(unzip '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
所以 apply
将对 (map list '(a b c) '(1 2 3) '($ % *))
的调用展平,而 list
接受任意元素,因此它最终的工作方式与上一个示例相同,但它也适用于其他维度:
(unzip '(a b c d) '(1 2 3 4))
; ==> ((a 1) (b 2) (c 3) (d 4))
map
的第一个参数是一个函数。此函数可能需要一个或多个参数。参数列表中的函数后面是一个或多个列表。
map
从列表的第一个元素到最后一个元素并行循环。
因此将每个列表的第 i 个位置作为函数的参数
并将结果收集到结果列表中 returns.
现在三个简短的例子可以让你清楚地图是如何遍历列表的:
(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))