不知道为什么,我很厌恶 map()

12 天前
 levelworm

首先声明一下,我承认我是个很烂的程序员。我甚至不愿意承认自己是程序员。(也许这就是原因?)

因为公司转向 Flink ,所以今天决定学习一下。但是不知道为什么,看到 map()就觉得生理上的厌恶,和看见一只蟑螂一样。

其实我自己也不能理解这种厌恶--我能理解为什么自己不喜欢,因为 map()本身没有可读性,你看到这个,就得去里头看到底是调用了什么函数。但是我不知道为什么我会有生理上的厌恶。同理,我在 PySpark 里看到 map(),也会极其厌恶,尤其是配合 lambda 食用,则更加厌恶。比如说

result = map(lambda x: x["id"], data["item"])

看到一次我就恶心一次。

不知道有没有类似的朋友,你们是如何克服的?我看了一下,Flink 里似乎无法避免 map()。所以只能自己习惯了。

5504 次点击
所在节点    程序员
44 条回复
iintothewind
12 天前
那是因为你用的 Python, 强类型动态语言, 而且传入参数没有 type hint 的原因吧.
你试试用用 Scala 不就好多了.
sagaxu
12 天前
跟你相反,我非常喜欢 map/filter/reduce/fold/chunk...,意图+操作,可读性强,且非常直观
levelworm
12 天前
@sagaxu #2
问题在于,map()意图清晰在哪里?只是知道要做个变换,具体是什么还得看里头啊。还是说我理解错了?

好吧,也许改成 transform()我就能接受了。真是奇怪的心理。
levelworm
12 天前
@iintothewind #1
有可能,但是我觉得 Python 那段,用 list comprehension 就好很多。
aresyang
12 天前
或许了解 fold_left mnist 后就还好
netabare
12 天前
不过是个 Functor 而已。

或者也许 Python 的 lambda 语法太丑了。要是换成 map (fn x => x + 1) [1,2,3,4] 这不就清晰多了吗。

List comprehension 这玩意能出现的前提是它是个 monad ,按照那个著名的话,monad 得先是个 functor ,换句话说能写出 list comprehension 的东西,它也肯定会写得出 map……这不就变成先有鸡还是先有蛋的问题了。
sagaxu
12 天前
@levelworm map 的清晰点在于,我不必定义一个 array/list 数据结构,然后把元素转换后 append 上去,而是直接告诉数据源,对这个集合的每个元素做一个映射,得到一个新集合,剥离了数据结构实现细节。你觉得别扭,可能是因为 python 的 lambda 语法不太友好。
w568w
12 天前
是这个 map 的命名和设计都比较反直觉。看到 map 这个单词,我大脑里的反应顺序是:

1. 创建 hashmap ?
2. 创建映射?
3. 哦都不对,是 ([a], f) -> [f(a)]

然后我自然的思考顺序是「对什么做映射?」,然后扫过第一个参数,发现是个很懵逼的 lambda 或者一个变量(然后往上翻了半天才发现这个变量是一个 function ),再仔细一想才发现不对,map 的第一个参数是映射……

参数顺序这一点非常反人体工学,因为中文这个语言先说上下文,比如会说「对某物做什么事」,而不常说「做什么事对某物」:我得先知道你在操作什么列表,然后你 lambda 函数里的各种引用、操作对我才有意义。把映射函数放在前面,对我来说是一个非常破坏阅读心智连贯性的设计。
levelworm
12 天前
@netabare 这倒是,不过我的确智商不足理解函数式编程,除非比较符合我的直觉。。。也可能用用就好了,反正逃不掉。
levelworm
12 天前
@sagaxu #7
这个我能理解,我其实就是不喜欢他叫 map 。。。R 的 apply 都好多了。我怎么这么矫情。
abc612008
12 天前
建议写写 ML 语言脱敏。或者写下 scala/kotlin 这种 map 比较好看的语言 e.g. `listOf(1,2,3).map{it * 2} == listOf(2,4,6)`
levelworm
12 天前
@abc612008 #11
好吧我承认我的智商不足以写 ML 系。。。
mizuhashi
12 天前
@w568w 函數式語言裏面 map 的返回值可以是一個函數,而且是可以組合的,所以例如 Haskell 可以這麼寫:`(map (+1) . map (*2)) [1, 2, 3]` 輸出 [3, 5, 7]。`map (*2)`返回一個可以把每個元素*2 的函數,然後`.`可以把兩個 map 的返回值連起來。不過 python 的 map 不知道有沒有這種性質,如果沒有的話確實沒必要把函數放前面。
9LCRwvU14033RHJo
12 天前
Flink 和 Spark 之所以使用 map 是因为它们受到了谷歌最早的 MapReduce 模型的启发。

使用这一套技术编写程序,可以轻松地利用集群的计算能力。map 操作将任务分解,并分发给多台机器同时处理。而 reduce 操作则将计算结果汇总到一个节点,从而得出最终结果。
nkcfc
12 天前
map 大概就是数学上的映射或者函数,当然得有个 f 和集合了,f 在前面不是很自然吗? apply 和 map 一般不同,用于支持任意多变量的函数。
nkcfc
12 天前
建议多学学数学,我现在受不了用 C 风格的代码计算这个例子,定义一个空数组,然后不断添加元素?
levelworm
12 天前
@nkcfc #16
没办法啊,各有所爱,能理解。
hefish
12 天前
支持 op 的讨厌。也支持我自己的不讨厌。
kagenomirai
12 天前
OP 只是不适应而已,就像第一次学极限的定义的时候,怎么看怎么恶心。
但后续理解了习惯了,不也一样用得飞起。
另外 python 的语法可读性我觉得太差了(太多 keyword 真影响阅读)。
当然最好的适应方式就是去学一个 ML 系的语言,学的过程中抛弃过程式的思考方式。
然后你就可以做到过程式和函数式两种思考方式之间任意切换了。
虽然只是为了一个 map 就花时间在 ML 上感觉有点浪费,不过程序员就是需要不断接受新东西(所以我本身也不喜欢程序员)。

关于 map 的命名。
其实首先登场的是 fmap ,意思是对一个 functor 进行映射。
functor 可以简单理解为一个复合数据,可以改变其中的元素同时不改变结构。
去掉 f 得到 map 的意思就是对一个特定数据映射(一般都是 list 或者 array )。
sir283
12 天前
这些动态语言的 map 跟 lambda 都不怎么好阅读,我觉得只有 C++跟 Java 的才好阅读。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/1108464

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX