Summary
While this document is long and detailed, the actual design reduces to a few major points.
Functions and types can have type parameters, which are defined using optional contracts.
Contracts describe the methods required and the builtin types permitted for a type argument.
Contracts describe the methods and operations permitted for a type parameter.
Type inference will often permit omitting type arguments when calling functions with type parameters.
This design is completely backward compatible, in that any valid Go 1 program will still be valid if this design is adopted (assuming contract is treated as a pseudo-keyword that is only meaningful at top level).
We believe that this design addresses people's needs for generic programming in Go, without making the language any more complex than necessary.
We can't truly know the impact on the language without years of experience with this design. That said, here are some speculations.
1
gamexg 2019-07-27 22:48:25 +08:00
这个大概什么时间能够用上?
|
2
trait 2019-07-27 23:53:57 +08:00 via iPhone 9
Why not use the syntax F<T> like C++ and Java?
When parsing code within a function, such as v := F<T>, at the point of seeing the < it's ambiguous whether we are seeing a type instantiation or an expression using the < operator. Resolving that requires effectively unbounded lookahead. In general we strive to keep the Go parser simple. 啧啧,go 语言组这么菜的吗,上次 try QA 也拿 parse 当说事,你们什么时候能认识到对用户 simple 和你实现 simple 不是一回事? |
4
useben 2019-07-28 00:11:22 +08:00
大概看了下,没有历史包袱就是好。引入了类似接口定义的约定和关键字 contract,看起来还不错
|
5
sillyousu 2019-07-28 00:14:38 +08:00
|
7
xfriday 2019-07-28 00:27:42 +08:00
大概看了下,contract 似乎可以取代 interface 了,功能更强
|
8
xfriday 2019-07-28 00:30:30 +08:00
@GM “ In general we strive to keep the Go parser simple.” 人家 go team 收你钱了?开发组有自己理念,你没有权利绑架,你不是上帝
|
9
lynskylate 2019-07-28 00:35:45 +08:00 via Android
@xfriday 开发者不是社区的一部分? go 不是社区驱动的?
|
10
sillyousu 2019-07-28 00:36:12 +08:00 1
|
11
lynskylate 2019-07-28 00:44:08 +08:00 via Android
@ipwx keep thr Go parser simple 这个实在是太不能理解了,一个编译器的前端和用户有什么关系,c++parser 留下了羡慕的眼泪
|
12
ptyfork 2019-07-28 00:53:51 +08:00
@GM
用 F<T> 就简单了? 那不过是用多了 java 先入为主而已。 引进范型就一定引入复杂度,对使用者和语言开发者都是负担,跟所用的语法关系反而关系不是很大 反而就目前 Go 中的设计,没有历史包袱,简单看了一下,跟 Go 语言之前的语法一致性保持的很好,对新手来说更友好。 |
14
reus 2019-07-28 02:12:54 +08:00
@xfriday 并不能,interface 是一个类型,例如 []io.Reader,在运行期,元素可以是任意实现了 io.Reader 的类型。但假如是 []T,那元素只能是特化了的那个类型。interface 是用于运行期动态分发的。
|
15
reus 2019-07-28 02:13:51 +08:00
@lynskylate go team 不是开发者一部分?整个编译器都是 go 写的,好不好用,他们自己不会判断啊?就你聪明。
|
16
reus 2019-07-28 02:24:16 +08:00
|
17
reus 2019-07-28 02:32:08 +08:00
@GM 难道把 () 改成 <>,就降低了复杂性?泛型就是以类型作为参数,既然是参数,那放在括号里,有什么问题? T(int) 就是以 int 为参数,特化出一个新的类型。
|
18
linghutf 2019-07-28 07:28:39 +08:00 via Android
什么时候能上?
|
19
nguoidiqua 2019-07-28 08:40:33 +08:00 via Android 1
很多人真是先入为主,老实说当初 Java 的泛型我是很迷糊的,当然搞熟了就会觉得很简单很自然了。
但如果你因为这样就觉得非此不可,那么就是自己封闭了自己认识新事物的能力,过去的习惯不知不觉就成了你思想的枷锁。 |
20
trait 2019-07-28 09:25:00 +08:00 via iPhone
@sillyousu 现在的 parser 技术实现 lookahead 不要太简单,这并不会让 go parser 更 simple
|
21
trait 2019-07-28 09:33:50 +08:00 via iPhone 9
某些 gopher 是没有任何思考能力的,当初有人抱怨为什么 err 这么简陋,为什么静态语言不给范型,这些人像传教士一样在各大论坛强行定义 simple,认为这些东西会让 go 过于复杂,如今 go 开始加这些“繁琐”特性,又开始各角度自洽
ugly =/= simple,连 parser 这种都有一套完整的自动化流水线模块都交给用户肉眼 parse,真的 simple |
22
pisc 2019-07-28 10:40:59 +08:00 via Android
|
23
mywaiting 2019-07-28 10:54:38 +08:00
看完楼上的回答,我决定继续写 python
|
24
Sasasu 2019-07-28 11:04:52 +08:00
啥时候有编译到 go 的语言
|
25
jhdxr 2019-07-28 11:23:35 +08:00 1
@reus 是是是,整个 v2 就你写过 parser。别的语言的实现也都全是傻逼 X。golang 最厉害了,吼不吼啊?
为什么要用于 F<T>? (对于有 C++/JAVA 经验的人)你看到的第一眼大概就能猜到这是什么东西。 (对于没有 C++/JAVA 经验的人)你看到的第一眼至少知道这是一个新玩意,并且绝对不会和 () 的那些语法混淆。 go 吹:没关系我自己累点眼花没事,parser 千万不能受累 |
26
artandlol 2019-07-28 11:29:00 +08:00 via Android
golang 相对于其他语言,赶紧更加严谨,所以会导致整体落后。跟苹果在很多功能方面落后安卓一个道理
|
27
rockyou12 2019-07-28 11:40:42 +08:00
写 python 要游标卡尺,写 go 以后要啥?啥东西数括号比较方便?
|
28
stephen9357 2019-07-28 11:43:03 +08:00 1
@reus 别杠了,Go team 是开发者的一部分,那 Golang 的使用者就不是了么?你这逻辑硬伤很严重。人家看不惯这种做法,表示反对怎么就不行了,非得 Golang 怎么做都叫好你才满意么,赶紧相互 block 吧,别瞎哔哔了,看着都尴尬。
|
29
wo642436249 2019-07-28 11:53:40 +08:00 via Android
看一堆人在这里争来争去,估计没有一个是在大厂工作😂
|
30
reus 2019-07-28 12:22:38 +08:00
@pisc go 这个提案的泛型参数并不能 currying,如果泛型需要 A, B, C 三个类型,那特化时就必须一起传入,并不能 currying。所以你的说法不成立。
|
31
scnace 2019-07-28 12:28:01 +08:00 via Android
contract 和 try 的概念大概 18 年就被 Go Team 提出来了吧 ,现在 try 被社区否决了,contract 还能活多久🙈
|
32
reus 2019-07-28 12:32:20 +08:00 3
@jhdxr parser 当然不能受累,编译快本来就是 go 的目标之一。别的语言不在乎编译速度,只是取舍不同,我可没有说过取舍不同就是傻叉,是你自己脑补的,别泼脏水啊。我可不是因为想吹 go 才这样说,纯粹是觉得有人傻逼,忍不住要吐槽啊。
所有 ML 系语言都是用 (),scala 用 [],D 用 (),Haskell 也没有 <>,为啥非得为了照顾一些连基本的学习能力都没有的人,而选择一种会带来歧义和降低编译速度的语法? 当然,如果 go team 能发现一种算法,让 <> 不需要 unbounded lookahead,我也能接受。本来就是个鸡毛蒜皮的事情,就只有菜鸡才纠结语法问题。go 连类型位置都和 C++ / java 不一样了,适应不了的人,何苦要用。 |
33
reus 2019-07-28 12:37:05 +08:00
@stephen9357 “看不惯”不是什么理性的理由,不是什么技术上的理由,纯粹是一个人学习能力低下,适应能力低下的表现。不用 <> 是有技术上的理由的,你不能用非理性非技术的理由,去反驳一个技术性的理由。
我是觉得“社区驱动”本来就是非常搞笑的事情,你社区驱动过什么了? |
34
hhjj3388 2019-07-28 12:38:54 +08:00
@jhdxr 没错··搞个() 让人混淆, 那个什么接收者也是 () 加参数() 加返回值()```````````````
|
35
ruimz 2019-07-28 12:51:46 +08:00 via Android
@reus 这个问题同样给你,你社区驱动过什么了?你没社区驱动过就觉得搞笑?
讨论就讨论,不要付诸人身攻击。 |
36
congeec 2019-07-28 12:52:52 +08:00 via iPhone
@trait #21 对啊。 规范和实现绑在一块儿的语言用起来就是别扭。python 是这样,js 是这样,还好 rust 已经开始移除 turbofish
::<>了 |
37
reus 2019-07-28 13:11:40 +08:00
@trait lookahead 从来都不是问题,问题在于时间复杂度,现在 go 语法用 lalr(1) 就能解析,O(n)就能解析,引入带歧义的语法,可能连 parser generator 都不能用了,像 C++ 一样。甚至需要引入 typename 这种纯粹是为了消除歧义的东西。
go 粉自然有傻逼,尤其是那些做培训的,本身水平就低,又整天喊“学不动”,尬吹什么大道至简。 go 黑的傻逼,不比这些 go 粉少,一看到和自己学过的东西有一点点不同,张嘴就是 ugly,为黑而黑。你跟他说技术原因,根本理解不了,根本就懒得去理解,整天想的就是怎么“黑”。 |
38
lynskylate 2019-07-28 13:14:24 +08:00 via Android
@congeec ?? python 规范和实现并不是绑在一起的啊,pypy jython ironpython,python 的各种实现有哪种语言比他多?唯一诟病的只有 c 拓展,python 暴露了太多内部细节导致 c 拓展不能在各种实现中迁移罢了
|
39
reus 2019-07-28 13:15:10 +08:00
@ruimz 我不知道你在说什么,“ go 是社区驱动的语言”,我认为是伪命题,语言设计,除了 go team 的人,有谁参与过? go module 更是直接否定社区的 dep。try 也不是社区“驱动”,而是社区“阻止”,毫无建设性的反对。
|
40
reus 2019-07-28 13:16:45 +08:00
@congeec go 有 google go, gcc go, llvm go, tiny go, gopherjs 等等实现,规范和实现不绑定
|
41
reus 2019-07-28 13:19:09 +08:00
@ruimz 我点进这个主题,本来也是想有技术上的讨论,谁知道看到一些菜鸡在那里拿些鸡毛蒜皮就说什么“这么菜”,“蛇精病”,实在忍受不了这些为黑而黑的人。
|
42
liulaomo 2019-07-28 13:31:39 +08:00
@reus
> “ go 是社区驱动的语言”,我认为是伪命题,语言设计,除了 go team 的人,有谁参与过? go module 更是直接否定社区的 dep。try 也不是社区“驱动”,而是社区“阻止”,毫无建设性的反对。 这个不完全对。很多人都参与,但基本上都被 Go team 给否决了, ;D |
43
liulaomo 2019-07-28 13:35:48 +08:00
其实不用<>可以理解,但是不用[],就有点难以理解了。难道要和内置范型走两条路线?
|
44
liulaomo 2019-07-28 13:41:28 +08:00
@reus 其实说“ go 是社区驱动的语言”,并不为过。虽然语言本身基本上都是 Go team 设计的,但是 Go 能走到今天,离不开很多关键社区项目选择了 Go,也离不开众多 contributors 提出的众多 issues。其实 Go 在某些方面并不是和现在很多使用了 Go 开发的项目,Go 只是一个在当时相对比较好的选择。Go 能走到今天,得感谢这些项目的选择(相互感谢吧)。
|
45
reus 2019-07-28 13:45:23 +08:00
@liulaomo 绝大部分都是水平不够,社区从来没有人能提出像这个泛型提案这种篇幅的完整设计。但就算设计好了,甚至实现了,像 dep,问题解决得不好,也同样会被官方否决。社区能参与的,也就对官方设计提提建议,或者 vendor 这种改动小的。
|
46
Hellert 2019-07-28 13:45:43 +08:00
现在的错误处理可以接受,泛型有没有也无所谓,啥时候把内置十进制小数 decimal 类型提上日程啊,写财务类的程序没有这个真是麻烦死。
|
47
reus 2019-07-28 13:48:50 +08:00
@liulaomo 那是对“ go 生态”的驱动,我前面说的其实是对“ go 语言”本身的驱动。我挺讨厌拿“社区”来绑架官方对语言的设计的人,自己一时不适应,甚至根本未完全理解一个设计,就提出反对
|
48
liulaomo 2019-07-28 13:51:00 +08:00
|
49
pisc 2019-07-28 14:48:25 +08:00 via Android
@reus 你居然用 ML、Haskell 举例。。。要用<>还是()说实话根本不要紧,不过就是考量怎么不显式用∀来引入 type variable 而已。
> 泛型就是以类型作为参数,既然是参数,那放在括号里,有什么问题? T(int) 就是以 int 为参数,特化出一个新的类型。 这是你的原话,我不是说 type level 之间是 currying 的,我说的是如果真像你说的,int 是很 trivial 的参数的话,为什么 type level 和 value level 之间是 currying 的,也就是 application 的时候是 T(int)(a, b)而不是 T(int, a, b),为什么?不就是 type parameter 和 value parameter 在 golang 并不是那么 trivial 的关系么,所以为什么()不见得比[]或<>好的原因,因为是不同的 level,用相同的符号是很容易有歧义的。 你要是像其他语言 type variable 和 value variable 都可以当作普通变量调用和传递,那当然没问题了,你又举了 haskell 的例子,haskell 用个毛的<>,haskell 本身就是 separated annotation 而且可以直接写∀,当然不用考虑这些幺蛾子了。 |
50
pisc 2019-07-28 14:53:12 +08:00 via Android
|
51
reus 2019-07-28 15:18:22 +08:00 via Android
@pisc 因为类型参数不是函数签名的一部分,所以放不同的括号。可以理解成两次“调用”,一次做特化,一次调用特化后的函数。阅读时就可以这样类比理解,而不是一看到没用<>就说什么不好读。我举例是想说明,不是每一门有泛型的语言都用<>,别扭曲我的原意。
我十分希望 go 不要火,不要吸引培训机构,不要有脑残粉,不要惹上你这样的(消音)黑。 |
52
tairan2006 2019-07-28 16:58:41 +08:00
`<>`这个是不是会降低编译速度呀,虽然语法本身无所谓的
|
53
duanquanyong 2019-07-28 17:36:38 +08:00
@tairan2006 语法也有所谓的, `<>` 是有歧义的,可以单独出现,作为小于号或者大于号
|
54
GM 2019-07-28 17:48:27 +08:00
|
55
dbskcnc OP 吵得是挺热闹的,但是似乎没 get 到重点
在 go 语言的设计原则下(简单不烧脑,便于工程实践,性能基本够用),增加泛型确实不是个轻松的事情,现有的其它语言解都有这样或者那样的弊端。 目前这个至少是衡量了各方面限制做出的一个可行解,放出来,经过各路神仙打磨,可用性还算是可以的,至少通用数据结构和算法库可以跟上当前编程语言界的水平 对于对此方案的各种意见,其实也只是我们各种 go 粉或者 go 黑的自 high 罢了,以 go team 浸淫计算机编程数几十年的功力,人家确实都懒得搭话,毕竟差距就是那么大,简单点就我们项目开发时一些新手的技术选型提议,多数只是天真的人云亦云罢了,真的很难有深刻的思考和实践 |
57
neoblackcap 2019-07-29 10:43:01 +08:00
@dbskcnc golang 作者原先就吐槽 C++的编译速度,因此他们坚持不能降低编译速度这个逻辑是自洽的。当然大家觉得好不好就另外一说。
不是说 go team 的经验足就代表他们比提案者厉害,有压倒性优势。大家都是受现代编译语言影响的人,提案者可不单单代表自己的知识储备,他还受这个业界最新的 PL 研究,多年来的 PL 实践影响。因此片面说其他人水平不够高是让人难以理解的。 其实不要说那么多,就是他们的追求跟大众的追求不协调而已。他们追求编译快速,自己觉得简单使用的语言,逻辑自洽。但是这说出来大家能接受吗?语言动了根本追求,哪怕是能做啊,那不就打了自己的脸?这才是根本问题。 |
58
laumm1314 2019-07-29 11:09:49 +08:00
范型怎么设计都不可避免其复杂性,go 引入范型是必须的么?
|
59
judeng 2019-07-29 11:18:03 +08:00
@jhdxr 为什么要用于 F<T>?
(对于有 C++/JAVA 经验的人)你看到的第一眼大概就能猜到这是什么东西。 (对于没有 C++/JAVA 经验的人)你看到的第一眼至少知道这是一个新玩意,并且绝对不会和 () 的那些语法混淆。 ----------------------- 如果是仅这个原因,我觉得 parser 更简单点好 |
60
dbskcnc OP @neoblackcap
1. 编译速度这个真的很有竞争力,使用 C++编译过大一点的系统,那感觉真的是解放(如果加上 go mod 的方便,那感觉就更不一样),当然也会有人指责说生成代码优化得不够好 2. go team 的人也不是原地踏步好不好,秒杀绝大部分人是没有问题的,当然三个臭皮匠顶个诸葛亮,go team 目前至少面上还是做了集思广益的工作 3. 这个很中肯,以目前 go 的水准,已经符合不少实际需要, 只是不少人也喜欢花衣裳 |
61
araraloren 2019-07-29 14:18:08 +08:00
感觉这里好多人都是咸吃萝卜淡操心,你是个语言的使用者,自然是怎么方便怎么来
简单即是复杂,parser 复杂不复杂和你们有多少关系?? |
62
reus 2019-07-29 22:41:06 +08:00 1
@araraloren 怎么没关系?编译时间变长,开发体验就下降了。原本 O(n) 跑完 parse 部分,现在可能要 O(n ^ 3),能忍?!
前段时间 cloudflare 被一个正则匹配搞挂一大片,你不要以为 parser / recognizer 真的是什么“自动化流水线模块”,文法不好处理,parser 分分钟榨干你的 CPU ! C++之前有近十年的时间,是不能连写 >> 的,一定要加个空格写成 > >。好处理的话,从一开始就不会出现这种问题。何况,() 和 <>,真的能分出谁方便谁不方便? |
63
lxml 2019-07-31 02:50:41 +08:00
go team 感觉截止到目前为止,感觉设计方案上没啥大坑,毕竟老头子们见得多了
|