为什么F#Interactive在不可变值定义方面的行为与编译器不同?

时间:2013-12-02 11:24:20

标签: f# immutability f#-interactive

在阅读John Palmer's What is the difference between mutable values and immutable value redefinition?的答案时,John注意到了

  

这种重新定义只适用于fsi。

在与F#Interactive(fsi)合作时,我想我下意识地知道它,但从未注意过它。

现在很明显,为什么会有区别?

更具体地说,请解释fsi和编译器之间的内部结构是如何不同的,这是通过设计或差异的结果发生的?

如果答案可以详细说明持有可以理解的绑定的内部结构。

1 个答案:

答案 0 :(得分:5)

语义与FSI将交互式提交编译为FSI会话的方式一致:每个交互式提交都编译为module,可以随后进行交互式提交。

以下内容接近FSI实际所做的事情,并说明了如何让绑定阴影在交互式提交中起作用:

FSI提交#1:let x = 1;;

module FSI_1 = 
    let x = 1

open FSI_1 //FSI_1.x is now bound to 1 and available at the top level

FSI提交#2:let x = 2;;

module FSI_2 = 
    let x = 2

open FSI_2 //FSI_1.x is now shadowed by FSI_2.x which is bound to 2 and available at the top level

您可以通过在FSI应用程序域中使用FSI_ASSEMBLY程序集上的反射来查看动态FSI程序集的编制方式的实际细节。每个交互式提交都是作为一个模块(.NET类)发出的,其命名模式为FSI_####。 FsEye使用这些事实来发现FSI顶级绑定的状态:https://code.google.com/p/fseye/source/browse/tags/2.0.1/FsEye/Fsi/SessionQueries.fs#24

关于@ JohnPalmer的答案的关键点是,顶层FSI定义不能被突变,当它们被“重新定义”时,它们只是被遮蔽。我们可以将其显示如下:

> let x = 1;; //our original definition of x
val x : int = 1

> let f () = x;; //capture x
val f : unit -> int

> let x = 2;; //shadow our original definition of x
val x : int = 2

> f();; //returns the original x value, which is still 1 rather than 2
val it : int = 1