【问题标题】:Why does F# Interactive behave differently than compiler with regards to immutable value definition?为什么 F# Interactive 在不可变值定义方面的行为与编译器不同?
【发布时间】:2017-07-30 13:08:54
【问题描述】:

在阅读John Palmer'sWhat is the difference between mutable values and immutable value redefinition? 的回答时,John 指出

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

在使用 F# Interactive (fsi) 时,我想我下意识地知道它,但从未注意它。

既然很明显,为什么会有差异?

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

如果答案可以详细说明保存绑定的内部结构,那将不胜感激。

【问题讨论】:

    标签: f# immutability f#-interactive


    【解决方案1】:

    语义与 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
    

    【讨论】:

    • 对于那些不熟悉FsEye 的人,您应该至少使用它一次,看看它的作用以及它如何为您提供帮助。我很少使用它,但是当我需要它时,没有其他东西可以很好地工作。谢谢斯蒂芬!
    • 我认为这里的 FSI 和编译行为之间的区别有点虚假。正如我在对原始问题的回答中所展示的那样,完全有可能在编译代码中重新声明(并因此隐藏)特定值。
    猜你喜欢
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    相关资源
    最近更新 更多