Julia: 不可变的复合类型

8

我对Julia仍然完全陌生,并对以下行为感到非常烦恼:

immutable X
  x::ASCIIString
end

"Foo" == "Foo"
true
X("Foo") == X("Foo")
false

但是使用Int而不是ASCIIString

immutable Y
  y::Int
end

3 == 3
true
Y(3) == Y(3)
true

我原本期待X("Foo") == X("Foo")是正确的。有人能解释一下为什么不是吗?
谢谢。
1个回答

5

Julia有两种相等比较方式:

  1. 如果你想检查x和y是否完全相同,即没有程序可以区分它们。那么正确的选择是使用is(x,y)函数,而用于执行此类比较的等效运算符是===运算符。棘手的部分在于,如果两个可变对象的内存地址相同,则它们相等,但是当您比较两个不可变对象时,is在位级别上返回true如果内容相同。

2 === 2 #=> true,因为数字是不可变的

"Foo" === "Foo" #=> false

  1. ==运算符或其等效的isequal(x,y)函数称为通用比较,如果首先存在适用于此类型参数的方法,并且其次该方法返回true,则返回true。那么如果该方法未列出怎么办?然后==调用===运算符。
现在针对上述情况,您有一个不可变类型,没有==运算符,因此您实际上调用了===运算符,并且它检查两个对象是否在位级内容上相同,但它们并不是因为它们引用不同的字符串对象,"Foo" !== "Foo"

编辑:

正如@Andrew所提到的,参考Julia文档,字符串是不可变数据类型,那么为什么"test"!=="true" #=> true?如果你深入了解字符串数据类型的结构,例如通过xdump("test") #=> ASCIIString data: Array(UInt8,(4,)) UInt8[0x74,0x65,0x73,0x74],你会发现字符串是由复合数据类型组成的,其中有一个重要的data字段。Julia字符串主要是字节序列,存储在字符串类型的data字段中。并且isimmutable("test".data) #=> false


1
我有点困惑,你说字符串是可变的,但是字符串文档上说"就像Java一样,字符串是不可变的"。 - Andrew
我犯了一个错误,isimmutable("test") #=> true,答案需要修改。 - Reza Afzalan
非常感谢。这不仅解释了行为,还展示了如何找到答案。所以我想要达到期望的行为,必须明确地定义。 - vonDonnerstein
[...] ==(x1::X,x2::X) = x1.x == x2.x。我误读了文档(http://julia.readthedocs.org/en/latest/stdlib/base/)中“集合通常通过递归调用所有内容的isequal来实现”的意思,认为这是集合类型的默认实现。但事实上,默认情况下,`X("Foo") == X("Foo")也是X("Foo") === X("Foo")`。所以再次感谢您提供的非常好的解释。 - vonDonnerstein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接