“==”和 "is" 运算符在 D 中究竟比较什么?
What exactly do the "==" and "is" operators compare in D?
从 "Programming in D" 书中我了解到 ==
运算符需要访问对象,以便在 returning 布尔值之前评估左侧和右侧的表达式。因此不适合比较对象是否为null
.
... the == operator may need to consult the values of the members of the objects and that attempting to access the members through a potentially null variable would cause a memory access error.
还有
Value equality: The == operator that appears in many examples throughout
the book compares variables by their values. When two variables are said to
be equal in that sense, their values are equal.
所以,让我们尝试以下操作:
import std.experimental.all;
int[] arr = [1, 1, 2, 2, 3];
arr == arr.reverse.array; // --> true
嗯,这是出乎意料的。例如在 Scala 中相同的表达式 returns False
。
检查arr
和arr.reverse.array
的内存地址后就更清楚了——它没有改变。所以,现在 ==
的结果有点道理,尽管人们希望它比较数组的值而不是它们的地址,对吧?
现在,让我们试试 is
运算符,它用于比较对象引用,应该用于检查对象是否为 null
。它还用于比较 class 个变量。
arr is arr.reverse.array; // --> false
我希望它也能 return true
因为它比较参考文献。这里到底发生了什么?为什么 is
returns false
而 ==
returns true
?
==
比较值。 is
比较引用。你的大错误是使用函数 reverse
.
http://dpldocs.info/experimental-docs/std.algorithm.mutation.reverse.html
Reverses r in-place.
强调我的。也就是说修改了原来的内容。
我怀疑你也查错了内存地址。如果使用 &arr
,则比较的是局部变量的地址,而不是数组内容。这不会改变,因为它是同一个局部变量,您只是绑定到一个不同的数组。检查 .ptr
而不是 &
,您会看到它发生了变化 - .array
函数总是为其分配一个新数组。
所以==通过了因为反向同时改变了左手边!这不是因为 [1,2,3] == [3,2,1],而是因为在调用 reverse 之后,[1,2,3] 本身被修改为 [3,2,1] 即== [3,2,1]!.
现在,关于这些运算符的实际作用:==
检查一些抽象的相等性。这因类型而异:它可以被成员函数覆盖(这就是为什么在 null
类 上调用它是有问题的)并且经常进行逐个成员比较(例如数组元素或结构片段) .
另一方面,is
做的事情要简单得多:它是直接对变量进行位比较,这更接近恒等式的抽象概念,但不完全是(如 int a = 3; int b = 3; assert(a is b);
通过,因为两者都是 3 但它是相同的标识吗?值类型的模糊 cuz。)
is
永远不会调用用户定义的函数,也永远不会下降到成员引用,它只是比较位值。
(有趣的是,float.nan is float.nan
也 returns 正确,而 == 不会,同样只是因为它比较位值。但并非所有 nans 都具有相同的位值,因此它不是替换数学模块中的 isNaN!)
从 "Programming in D" 书中我了解到 ==
运算符需要访问对象,以便在 returning 布尔值之前评估左侧和右侧的表达式。因此不适合比较对象是否为null
.
... the == operator may need to consult the values of the members of the objects and that attempting to access the members through a potentially null variable would cause a memory access error.
还有
Value equality: The == operator that appears in many examples throughout the book compares variables by their values. When two variables are said to be equal in that sense, their values are equal.
所以,让我们尝试以下操作:
import std.experimental.all;
int[] arr = [1, 1, 2, 2, 3];
arr == arr.reverse.array; // --> true
嗯,这是出乎意料的。例如在 Scala 中相同的表达式 returns False
。
检查arr
和arr.reverse.array
的内存地址后就更清楚了——它没有改变。所以,现在 ==
的结果有点道理,尽管人们希望它比较数组的值而不是它们的地址,对吧?
现在,让我们试试 is
运算符,它用于比较对象引用,应该用于检查对象是否为 null
。它还用于比较 class 个变量。
arr is arr.reverse.array; // --> false
我希望它也能 return true
因为它比较参考文献。这里到底发生了什么?为什么 is
returns false
而 ==
returns true
?
==
比较值。 is
比较引用。你的大错误是使用函数 reverse
.
http://dpldocs.info/experimental-docs/std.algorithm.mutation.reverse.html
Reverses r in-place.
强调我的。也就是说修改了原来的内容。
我怀疑你也查错了内存地址。如果使用 &arr
,则比较的是局部变量的地址,而不是数组内容。这不会改变,因为它是同一个局部变量,您只是绑定到一个不同的数组。检查 .ptr
而不是 &
,您会看到它发生了变化 - .array
函数总是为其分配一个新数组。
所以==通过了因为反向同时改变了左手边!这不是因为 [1,2,3] == [3,2,1],而是因为在调用 reverse 之后,[1,2,3] 本身被修改为 [3,2,1] 即== [3,2,1]!.
现在,关于这些运算符的实际作用:==
检查一些抽象的相等性。这因类型而异:它可以被成员函数覆盖(这就是为什么在 null
类 上调用它是有问题的)并且经常进行逐个成员比较(例如数组元素或结构片段) .
is
做的事情要简单得多:它是直接对变量进行位比较,这更接近恒等式的抽象概念,但不完全是(如 int a = 3; int b = 3; assert(a is b);
通过,因为两者都是 3 但它是相同的标识吗?值类型的模糊 cuz。)
is
永远不会调用用户定义的函数,也永远不会下降到成员引用,它只是比较位值。
(有趣的是,float.nan is float.nan
也 returns 正确,而 == 不会,同样只是因为它比较位值。但并非所有 nans 都具有相同的位值,因此它不是替换数学模块中的 isNaN!)