什么是之间的“等号(=)”和“(==)相同的” OCaml中的区别?(What's the

2019-07-04 04:50发布

OCaml ,我们有两种equity comparisons

x = yx == y

那么什么是确切它们之间的区别?

x = y OCaml中就像x.equals(y)在Java中?

x == y就像x == y (comparing the address)在Java中?

Answer 1:

我不知道究竟如何x.equals(y)在Java中工作。 如果是这样一个“深”的比较,那么这个比喻相当接近。 有一两件事要小心的是,物理平等是OCaml中(和一般的函数式语言)一个难以把握的概念。 编译器和运行时系统会左右移动值,并可能合并,随意拆分的纯(非可变)值。 所以,你应该只使用==如果你真的知道自己在做什么。 在某种程度上,它需要与熟悉的实现(这是一件好事,以避免,除非必要)。

这使得ocaml的为特定担保==薄弱。 可变值比较,如你所期望的方式平等物理(即,如果变异的两个人会真正发生变异另外也)。 但对于非可变值,唯一的保证是,这比较实际值相等( == )也将比较结果相等( = )。 请注意,反之则不然 ,因为sepp2k指出了浮动值。

从本质上说,什么语言规范告诉你不可变值是可以使用==作为一个快速检查,以决定是否两个非可变值相等( = )。 如果他们身体比较平等的,他们是平等的价值,明智的。 如果他们不比较实际平等的,你不知道,如果他们是平等的价值,明智的。 你仍然必须使用=来决定。



Answer 2:

编辑:这个答案再往OCaml的内部工作,立足于对细节Obj模块。 这种认识并不意味着没有格外小心使用(让我强调这一点很重要一次:不要使用你的程序,但前提是你希望与OCaml的运行试验 )。 这些信息也可以,虽然或许在O'Reilly的书OCaml中更容易理解的形式,可在线 (还不错的书,虽然有点现已过时)。

=操作者检查结构相等,而==只检查物理平等。

平等检查是基于价值的分配和存储在存储器中的方式。 OCaml中运行时值可大致配合到2个不同的类别:要么盒装装箱 。 前者意味着该值是内存可达通过间接和后来的手段,该值是直接访问。

由于int (在32个系统INT31,或int63在64位系统)是未装箱值,两个运营商都表现与它们相同。 一些其他类型或值,其运行时的实施方式实际上是int ,也将看到两个操作行为与它们相同,像单元()空列表[]在代数数据类型和多态变体,等常数

一旦你开始使用更复杂的价值观,涉及结构玩耍,如列表,数组,元组,记录(在C结构等价物),这两个运营商之间的差异出现了:结构中的值将被装箱,除非他们可以表示为本地整数运行(1)。 这种必要性源于运行时系统必须如何处理价值,并有效地管理内存。 从其他的值,其可以是自身结构化值,在这种情况下的附图标记用于(因为它们被框)构造时的结构化值被分配。

由于分配的,这是不太可能,在程序的不同点实例化两个值可能是物理上相等,但他们会在结构上相同。 每个字段或值的范围内内要素可以是相同的,甚至高达物理身份,但是如果这两个值是动态建立,则它们将最终中存储器使用不同的空间,并且因此在物理上不同,但结构上等于。

运行时试图避免不必要的分配,但:举例来说,如果你有一个函数总是返回相同的值(换句话说,如果函数是恒定的),简单或结构化,该功能将始终返回相同的物理值(即在存储器中的相同的数据),以便测试物理平等该函数的两个调用的结果将是成功的。

观察时,物理运算符实际上将返回一个办法true是使用Obj.is_block功能在其运行时表示(也就是说,结果Obj.repr就可以了)。 这个函数简单地告诉它的参数运行时表示是否被装箱。

更做作的方法是使用下面的函数:

let phy x : int = Obj.magic (Obj.repr x);;

该函数将返回一个int是指针绑定到值的实际值x在存储器中,如果该值被装箱 。 如果你尝试在一个int文字,你会得到完全相同的价值! 这是因为INT是装箱 (即该值直接存储在存储器中,不是通过引用)。

现在我们知道,盒装值实​​际上是“引用”的价值观,我们可以推断,这些数值可以被修改,即使语言说,他们是不可改变的。

考虑实例的引用类型:

# type 'a ref = {mutable contents : 'a };;

我们可以定义一个不变的裁判是这样的:

# type 'a imm = {i : 'a };;
type 'a imm = {i : 'a; }

然后使用Obj.magic函数来强迫一种类型到另一个,因为在结构上,这些类型的将减少到相同的运行时表示。

例如:

# let x = { i = 1 };;
- : val x : int imm = { i = 1 }
# let y : int ref = Obj.magic x;;
- : val y : int ref = { contents = 1 }
# y := 2;;
- : unit = ()
# x
- : int imm = { i = 2 }

有一些例外情况:

  • 如果值是对象,则即使看起来结构相同的值将返回false关于结构比较

     # let o1 = object end;; val o1 : < > = <obj> # let o2 = object end;; val o2 : < > = <obj> # o1 = o2;; - : bool = false # o1 = o1;; - : bool = true 

    在这里,我们看到=恢复到物理等价。

  • 如果值的功能,你不能在结构上对它们进行比较,但是体质比较按预期工作。

  • 懒惰值可以是或可以不是在结构上相当的,这取决于它们是否已被强迫或不(分别地)。

     # let l1 = lazy (40 + 2);; val l1 : lazy_t = <lazy> # let l2 = lazy (40 + 2);; val l2 : lazy_t = <lazy> # l1 = l2;; Exception: Invalid_argument "equal: functional value". # Lazy.force l1;; - : int = 42 # Lazy.force l2;; - : int = 42 # l1 = l2;; - : bool = true 
  • 模块或记录值也是可比的,如果他们不包含任何功能价值。

在一般情况下,我想这是肯定地说,这是有关的功能,或者可以内部保持功能值不具有可比性= ,但可进行比较==

很显然你应该非常谨慎着这一切 :依靠运行时的实现细节是不正确的 (注:我开玩笑地用这个词在我这个问题的答案的最初版本,但改变了它被恐惧它正在采取太认真)。 正如你在恰当的评论中指出,JavaScript实现的行为是不同的浮动(在JavaScript结构相当的,但不是在参考实现,以及有关Java一个什么呢?)。


(1)如果我没有记错,花车也未装箱的存储阵列时避免双重间接引用,但他们成为盒装提取一次,所以你不应该在行为上看到有盒装值的差异。



Answer 3:

在ocaml的是X = Y就像在Java中x.equals(y)的?

并且x ==Ÿ就像X ==Ÿ在Java中(比较地址)?

对,就是那样。 除了OCaml中可以使用=在每一种价值,而在Java中,你不能使用equals上基本类型。 另一个区别是,OCaml中浮点数是引用类型,所以你不应该使用他们比较== (不,它通常是一个好主意,浮点数直接平等反正比较)。

因此,在总结,你基本上应该总是用=来比较任何类型的数据。



Answer 4:

根据http://rigaux.org/language-study/syntax-across-languages-per-language/OCaml.html , ==检查浅平等,和=检查深平等



文章来源: What's the difference between “equal (=)” and “identical (==)” in ocaml?