运算符重载有什么实际用途?感觉很鸡肋 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
seekseat
V2EX    Go 编程语言

运算符重载有什么实际用途?感觉很鸡肋

  •  
  •   seekseat 2024-09-07 17:58:19 +08:00 7397 次点击
    这是一个创建于 397 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看到很多人在讨论...但这玩意有啥作用,工作这么多年完全没 get 到

    54 条回复    2024-11-27 19:12:20 +08:00
    nino
        1
    nino  
       2024-09-07 18:05:21 +08:00   1
    对写 DSL 和 库的人才有意义,能让 API 更语义化,或者语句更像数学公式
    cwek
        2
    cwek  
       2024-09-07 18:06:39 +08:00   1
    "语句更像数学公式",就是这个。
    hanxiV2EX
        3
    hanxiV2EX  
       2024-09-07 18:21:36 +08:00 via Android
    golang 要支持了吗?
    echo1937
        4
    echo1937  
       2024-09-07 18:31:52 +08:00
    mainjzb
        5
    mainjzb  
       2024-09-07 18:34:48 +08:00   6
    实现矩阵相乘 ,相加
    result := a1 * a2 + a3
    而不是
    result := sum(mul(a1, a2) , a3)

    比如连接
    result := s1 + s2
    而不是
    result := strings.append(s1, s2)

    比如实现一个 @ 代替 must( func f() ) 来简化错误处理
    result := @runServer()
    而不是
    result := must(runServer())

    比如检测一堆向量是否能形成环
    sum := vector(0,0)
    for _,v := range vs{
    sum += v
    }
    if sum == vector(0,0) {
    // 形成了环
    }

    而不是

    sum := vector(0,0)
    for _, v:= range vs{
    sum = vectors.add(sum, v)
    }
    if sum.x == 0 && sum.y == 0 {
    // 形成了环
    }
    laminux29
        6
    laminux29  
       2024-09-07 19:05:44 +08:00
    举个更简单的例子,无论 C++、Java 、C#、Python ,大家都喜欢用 Class 或 Struct 。这玩意本质上来说,就是对基础数据结构的包装,或者说是语法糖。如果没有 Class 、Struct ,你自己得用一大堆基础数据结构的数组或 List ,来自行管理这些玩意,于是,这个问题,就转换为:

    Class 、Struct 有什么实际用途?
    Ayanokouji
        7
    Ayanokouji  
       2024-09-07 20:01:26 +08:00
    运算符重载 我只佩服 kotlin
    xgdgsc
        8
    xgdgsc  
       2024-09-07 20:25:34 +08:00 via Android
    Sawyerhou
        9
    Sawyerhou  
       2024-09-07 20:27:22 +08:00 via Android   11
    举个栗子

    Python 里 pathlib 拼接路径,
    不必用+,不必用 join ,用/

    dir / "stem.csv"

    非常直觉,高效又易读,
    每次我用到都感慨这个重载太漂亮了。
    PopRain
        10
    PopRain  
       2024-09-07 21:00:18 +08:00
    第一次用 Java , 被 BigDecimal interest = loanAmount.multiply(interestRate) 震惊了。。。。。
    ty29022
        11
    ty29022  
       2024-09-07 21:17:19 +08:00   5
    @Sawyerhou 这个我认为恰恰是个反面例子
    在我看来编程语言中 / 就是除法,读出来是除法,做的事情也该是除法
    这和向量和矩阵操作这种符合数学直观逻辑的用法很不一样
    不过这很 python 就是了,个人感觉 python 总是做一些自以为”自然“的事情
    wlingxiao
        12
    wlingxiao  
       2024-09-07 22:01:34 +08:00
    建议看看 scala ,体会下操作符满天飞的感觉。
    cmdOptionKana
        13
    cmdOptionKana  
       2024-0907 22:03:19 +08:00
    确实很鸡肋,实用性不强,主要用途是耍帅。
    GeruzoniAnsasu
        14
    GeruzoniAnsasu  
       2024-09-07 22:04:24 +08:00
    @ty29022
    那 numpy 重载切片运算符倒确实还挺自然的
    shintendo
        15
    shintendo  
       2024-09-07 22:06:15 +08:00   1
    @ty29022 我感觉 python 的三目也有点……
    masterclock
        16
    masterclock  
       2024-09-07 22:24:36 +08:00
    没有操作符重载写点计算的东西简直就是折磨啊
    wxf666
        17
    wxf666  
       2024-09-07 22:25:28 +08:00
    @ty29022 #11 为嘛 / 只能是除法的意思,而不能是分隔符呢?(比如斜杠青年)

    那同理,字符串拼接,也不该用 +,而是像拼接矩阵那样,[str1 str2 str3] ?

    wxf666
        18
    wxf666  
       2024-09-07 22:39:32 +08:00
    @PopRain #10 有没有 greaterEqualThan() 啥的。。

    还是叫 greaterThanOrEqualTo()。。

    Sawyerhou
        19
    Sawyerhou  
       2024-09-07 22:41:09 +08:00
    @ty29022 重载运算符跟语言没有关系,支持重载都可以用/拼接路径。

    做数学的应该都知道符号是非常不够用的,符号在不同域下定义不一样很正常,
    *在初等数学里是乘法,高等里就是卷积了。

    而且路径的对象类型不属于数学对象,没有除法
    就像,C++里面 IO 流用<<和>>,IO 本身也没有比较大小的必要。
        20
    newtype0092  
       2024-09-07 22:54:48 +08:00
    想想确实除了在学校里课上花了好大功夫学了一番,实际工作中并没有怎么用上过。

    每次想实践一下,总觉得我写的那些东西还不配让别人迁就我来适应一个新的运算符用法,老老实实 function 加参数就好。
    009694
        21
    009694  
       2024-09-07 23:10:48 +08:00 via iPhone   1
    @ty29022 你这种想法极其傲慢。。 键盘上半角符号就这么几个 照你这说法全都只能用于原始的数学含义 那还真出什么运算符重载 全都只支持基础类型就行了
    nagisaushio
        22
    nagisaushio  
       2024-09-07 23:23:10 +08:00 via Android
    @ty29022 @Sawyerhou 有种给 iostream 左右移的美感(开玩笑)
    y1y1
        23
    y1y1  
       2024-09-07 23:37:10 +08:00
    确实当初下了好大的功夫
    wkla
        24
    wkla  
       2024-09-07 23:40:21 +08:00
    在 C++里,比如你写个类,重载一下移位运算符,就可以用左移右移来做输入输出 << >>

    C++ 的 filesystem 标准库,也可以用 / 运算符来算路径。比如 std::filesystem::path outputPath = std::filesystem::path("parent_dir") / relativePath;

    你写一套矩阵库,别人想用起来要是可以直接用 + - * / ,直接 << 输出,可能学习成本就低一点,别人会爽一点。

    虽然我确实觉得主要是用来耍帅
    f0rb
        25
    f0rb  
       2024-09-07 23:46:28 +08:00
    那路径里面 windows 的\怎么处理呢,只在 linux 上开发?
    aliipay
        26
    aliipay  
       2024-09-08 00:10:04 +08:00
    @009694 说实在的,这就是 shit,连标点都没有
    adoal
        27
    adoal  
       2024-09-08 00:10:40 +08:00   1
    @ty29022 运维人表示 / 显然是路径分割符……话说回来,数学课本里除法写一行用除号 ÷ ,写多行用分数线,斜线并不是主流啊。
    agagega
        28
    agagega  
       2024-09-08 01:45:39 +08:00
    严格一点说,大部分语言的运算符即使不支持用户重载,也是已经重载过的了。比如加法 + 严格来说对整数和浮点数是完全不一样的两种操作,像 OCaml 就会区分整数的 + 和浮点数的 +.

    所以严格纠结所谓数学上的含义没有意义……
    inframe
        29
    inframe  
       2024-09-08 04:06:01 +08:00
    @ty29022 #11 有点教条主义,从实用主义的角度出发工具的发明应该是提高生产效率的,
    “黑猫白猫不管什么猫,能让开发人员更加快速的完成开发任务就是好猫”
    whusnoopy
        30
    whusnoopy  
       2024-09-08 09:22:40 +08:00
    比如我定义了一个向量类型 P ,有 x/y 两个坐标,向量可以加一个向量到新的位置,就是 p3(x3, y3) = (x1+x2, y1+y2), 如果支持运算符重载,在向量类型定义里我重载掉加法,这样我就只要写 p3 = p1 + p2 就行,而不用写 p3.x = p1.x + p2.x ,p3.y = p1.y + p2.y
    p1gd0g
        31
    p1gd0g  
       2024-09-08 09:40:38 +08:00
    说白了还是看业务,总没必要硬着头皮用吧?
    mightybruce
        32
    mightybruce  
       2024-09-08 09:48:42 +08:00
    这个是语言哲学语言设计的范畴,无所谓好坏,支持运算符重载能找到一堆理由,不支持运算符重载的也有一堆理由。

    新语言如 rust 也有通过 trait 来支持运算符重载的
    liuminghao233
        33
    liuminghao233  
       2024-09-08 09:58:45 +08:00 via iPhone
    10 个矩阵相乘,你用 golang 写一下吧
    R4rvZ6agNVWr56V0
        34
    R4rvZ6agNVWr56V0  
       2024-09-08 10:22:28 +08:00
    高级抽象:除 1 楼提到的 DSL 外,还有场景,如 ORM
    butanediol2d
        35
    butanediol2d  
       2024-09-08 10:40:56 +08:00   1


    情绪化日志( doge
    default996
        36
    default996  
       2024-09-08 10:44:40 +08:00
    @butanediol2d 哈哈,为什么不把表情符号也追加到日志中
    wanguorui123
        37
    wanguorui123  
       2024-09-08 10:48:37 +08:00   1
    C# 里面运算符重载可以实现+注册和-移除方法实现更直观的订阅机制
    Biem
        38
    Biem  
       2024-09-08 11:01:34 +08:00
    @ty29022 读出来是除法只能说明一件事,那就是命名不规范不能体现变量或者函数的实际意义。
    Kauruus
        39
    Kauruus  
       2024-09-08 11:01:54 +08:00
    你用过 Go 的 math/big (或者其他 decimal 包)就知道了,他们的加减乘除是这样的:

    ```
    func (z *Int) Add(x, y *Int) *Int
    func (z *Int) Sub(x, y *Int) *Int
    func (z *Int) Mul(x, y *Int) *Int
    func (z *Int) Quo(x, y *Int) *Int
    ```

    本来一行就能写完公式,你用上面的 API 要不断搞中间变量,硬是写成十几二十行,每次写点复杂的计算公式或者 code review ,我就头大,非常想要运算符重载。
    sazima
        40
    sazima  
       2024-09-08 11:07:13 +08:00
    比如这个, 运算符就重载了,sesseion.User.filter(User.name == User.nickname | User.age < 15 )
    araraloren
        41
    araraloren  
       2024-09-08 11:38:06 +08:00
    所以,go 是不支持么,理由是什么?然后怎么就推翻了自己
    tool2dx
        42
    tool2dx  
       2024-09-08 11:46:36 +08:00 via Android
    最明显就是向量数学类,能和普通的语法一样加减乘除。
    别的似乎也没明显好处。
    yb2313
        43
    yb2313  
       2024-09-08 13:24:09 +08:00
    又想写 equals 了是吧
    nenseso
        44
    nenseso  
       2024-09-08 14:52:21 +08:00
    ==啊这种两个数据结构的比较重载一下还是很好用的,也很好读
    wsping
        45
    wsping  
       2024-09-08 15:57:02 +08:00   1
    自定义类要排序的话就必须重载小于号
    AV1
        46
    AV1  
       2024-09-08 16:35:14 +08:00
    a + b 本质就是 a.add(b) 的语法糖。
    如果平时开发都是以 crud 为主,那确实看起来差别不大。
    但如果是以数学计算为主的开发,重载后的+-*/之类的符号是比方法名看得更舒服的。
    lance6716
        47
    lance6716  
       2024-09-09 00:09:21 +08:00 via Android
    让自定义结构体长的跟内置类型一样,不过个人觉得没必要,妈的 debug 的时候看上去人畜无害的一样结果是个重载
    guiyumin
        48
    guiyumin  
       2024-09-09 00:15:29 +08:00
    @wsping nice
    dragondove
        49
    dragondove  
       2024-09-09 08:34:24 +08:00
    运算符重载有个好处是可以利用运算符的优先级减少括号层数而使代码变得易读。例如创建 sql 的 dsl 时,如果使用 where ((a add b) eq c) and (d eq e) 对比 where a + b == c && d == e 来说,后者更易读
    jorneyr
        50
    jorneyr  
       2024-09-09 09:10:17 +08:00
    @PopRain 本来没啥感触,您一提到 BigDecimal 我就有点炸裂了。
    caiqichang
        51
    caiqichang  
       2024-09-09 10:16:22 +08:00
    建议看一下《 effective c++》和《 more effective c++》中运算符重载的相关内容
    cybort
        52
    cybort  
       2024-09-09 18:38:03 +08:00 via Android
    高级语言有什么用处?写汇编不行吗?
    Rickkkkkkk
        53
    Rickkkkkkk  
       2024-09-09 19:26:15 +08:00
    你肯定期望能写 "sss" + "ddd" 这种啊...也符合直觉
    Miranquil
        54
    Miranquil  
       316 天前
    运算符重载有没有用呢?看楼上感觉没啥大用。
    := 有没有用呢? var variable type 完全满足了,:= 有时还会因为 shadowing 引出一些问题,但你离得开 := 么?

    题外话:实际上开始思考这些内容是一个好的开始,先不说重载有没有用,本身这个事情很好……
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1152 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    Wold is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 23:28 PVG 07:28 LAX 16:28 JFK 19:28
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86