『软件工程』计算机界 TOP 3 难题:“相等”是软件工程中许多重大问题的根源
有一个笑话说 , 计算机科学界有两大难题:一是缓存失效问题 , 二是命名问题 。 但我认为还有第三个更难的问题:相等问题 。 你没看错 , 等号“=”看似简单 , 但等号的使用和误用 , 是软件工程中许多重大问题的根源 。
声明:本文已获作者Craig Stuntz翻译授权 。
本文插图
作者 | Craig Stuntz
译者 | 弯月 , 责编 | 郭芮
头图 | CSDN 下载自视觉中国
出品 | CSDN(ID:CSDNnews)
以下为译文:
本文插图
相等的原理
我来展示一下在编程语言中相等有多么容易出错 。 但首先我要解释一下相等应有的模样 , 而这其实非常难解释!当我们讨论相等“应该如何”时 , 我们必须指出是特定语境下的相等 , 因为相等的成立有许多方式 , 许多方式在不同的语境下都是成立的 。
“数学的精髓在于 , 同一个东西可以用不同的方式呈现给我们 。 ”
——Barry Mazur , 《When is one thing equal to some other thing》
定律
我说过 , 在不同的语境下 , 相等有不同的含义 , 但尽管如此 , 有些东西是永远成立的 。 这就是相等的定律 。
相等是一个二元操作 , 它是:
- 反射的 , 即对于任意值 a 都有 a = a
- 对称的 , 即a = b可以推出b = a , 反之亦然
- 传递的 , 即如果a = b且b = c , 则a = c
相等必须是:
- 一致的 , 即如果a = b且a或b的任何字段都没有发生变化 , 那么稍后再次检查时a = b应当依然成立 。
结构相等性
在编程语言对于相等的各种实现中 , 一个重要的区别就是结构相等和引用相等 。
结构相等会检查两个引用是否为同一个值 。 F#默认采用了结构相等:
type MyString = { SomeField : string }let a = { SomeField = "Some value" }let b = { SomeField = "Some value" }if a = b then // 返回true, 进入 "then" 代码块 但在C#中则不是这样 , C#使用的是引用相等 。 引用相等要求两个被比较的对象是同一个对象 。 换句话说 , 它会比较两个变量是否指向同一个内存地址 。 指向两个不同内存地址的引用会被判为不相等 , 即使它们的值完全一样: class MyString { private readonly string someField; public string SomeField { get; } public MyString(string someField) => this.someField = someField;}var a = new MyString("Some value");var b = new MyString("Some value");if (a == b) { // 返回 false, 不会进入代码块 其他语言会让你选择 。 例如 , Scheme提供了equal?来检查结构相等 , eq?来检查引用相等 。 Kotlin提供了==用于结构相等 , ===用于引用相等(不要与JavaScript的==和===操作符混淆 , JavaScript的那个是完全不同的东西) 。程序中何时应当使用结构相等?如果变量的值不会改变更 , 那么几乎任何情况下都应该使用结构相等!我所知的绝大多数编程语言在诸如integers之类的类型上都使用结构比较 。 除了Java之外 , int类型进行结构比较 , Integer类型进行引用比较 , 这迷惑了一代又一代的程序员 。 Python的is也有类似的问题 。
推荐阅读
- Q1全球电视出货量公布:海信跻身TOP3,竞争转向价值战
- 【数据中心专家Top】光模块基本知识
- 「微型计算机」打造“小钢炮”别只顾机箱主板!SFX电源应该这样选
- 微型计算机@打造“小钢炮”别只顾机箱主板!SFX电源应该这样选
- @2020中国TOP100独角兽企业发展现状、机遇与挑战分析
- 极速聊科技:华为河图横空出世,【计算机-胡又文】打造AR数字底座
- TOPWOMEN时髦笔记@撞脸Jennie堪称芭比娃娃,未来YG的门面担当,仅11岁坐拥百万粉丝
- 「数据中心专家Top」光模块基本知识
- 「娱乐圈小松鼠」第一热度高达85.9,电视剧全网热度榜Top5:《安家》挤进前五
- 『倚心于生活』计算机破译需100万年,中国女子只用了2年,美国的超难密码
