在阅读John Palmer's What is the difference between mutable values and immutable value redefinition?的答案时,John注意到了
这种重新定义只适用于fsi。
在与F#Interactive(fsi)合作时,我想我下意识地知道它,但从未注意过它。
现在很明显,为什么会有区别?
更具体地说,请解释fsi和编译器之间的内部结构是如何不同的,这是通过设计或差异的结果发生的?
如果答案可以详细说明持有可以理解的绑定的内部结构。
答案 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