在OCaml中有!=有意义吗?
这似乎是一些types的等价比较,但不是string。
# 3 != 3;; - : bool = false # 3 != 2;; - : bool = true
这是预期的。
# "odp" = "odp";; - : bool = true # "odp" != "odp";; - : bool = true # "odp" <> "odp";; - : bool = false
为什么"odp" != "odp"
评估为true
? 它究竟在做什么? 它不应该产生一个types错误?
你经历了结构和物质平等之间的差异。
<>
=
is to =
(structural equality)as !=
is ==
(physical equality)
"odg" = "odg" (* true *) "odg" == "odg" (* false *)
是错误的,因为每个实例化在不同的内存位置,做:
let v = "odg" v == v (* true *) v = v (* true *)
大多数时候你会想要使用=
和<>
。
编辑关于何时结构和物理上的平等是等价的 :
你可以使用what_is_it函数 ,找出所有在结构和物理上都相等的types。 正如在下面的评论和链接的文章中所提到的,字符,整数,单位,空列表和变体types的一些实例将具有该属性。
!=
运算符的反义词是==
运算符,而不是=
1。
# "a" != "a" ;; - : bool = true # "a" == "a" ;; - : bool = false
==运算符是一个“物理平等”。 当你键入"a" == "a"
,你比较两个看起来相似的string的不同实例 ,所以运算符返回false
。 有一个实例会使其返回true:
# let str = "a" in str == str ;; - : bool = true # let str = "a" in str != str ;; - : bool = false
关于OCaml中==
和!=
快速解释,以及已经提供的所有正确答案:
1 / ==
和!=
公开你实际上不想知道的实现细节。 例:
# let x = Some [] ;; val x : 'a list option = Some [] # let t = Array.create 1 x ;; val t : '_a list option array = [|Some []|] # x == t.(0) ;; - : bool = true
到目前为止,这么好: x
和t.(0)
在物理上是相等的,因为t.(0)
包含一个指向x
所指向的同一块的指针。 这是执行的基本知识所要求的。 但:
# let x = 1.125 ;; val x : float = 1.125 # let t = Array.create 1 x ;; val t : float array = [|1.125|] # x == t.(0) ;; - : bool = false
你在这里看到的是一个涉及浮点数的其他有用的优化的结果。
2 /另一方面,有一个安全的方式来使用==
,这是一个快速,但不完整的方法来检查结构的平等。
如果你在二叉树上写一个相等函数
let equal t1 t2 = match ...
检查t1
和t2
是否物理平等是一种快速检测结构明显相等的方法,甚至不需要recursion和读取。 那是:
let equal t1 t2 = if t1 == t2 then true else match ...
如果你记住,在OCaml中,“boolean or”操作符是“懒惰”的,
let equal t1 t1 = (t1 == t2) || match ...
他们就像你们class的两个“汤姆”! 因为:
在这种情况下, "odp" = "odp"
因为它们是相同的 两个string值!!
所以他们不是==
因为他们是两个不同的string存储在不同的 (内存) 位置
他们是=
因为他们有相同的string值 。
再深一步,“odp”就是匿名variables。 而两个匿名variables导致这两个string。
为了您的方便:
# "odp" = "odp";; - : bool = true # "odp" != "odp";; - : bool = true # "odp" <> "odp";; - : bool = false
整数是物理和结构相等的唯一types,因为整数是唯一被拆箱的types