Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does F# Interactive behave differently than compiler with regards to immutable value definition?

In reading John Palmer's answer to What is the difference between mutable values and immutable value redefinition?, John notes that

This sort of redefinition will only work in fsi.

In working with F# Interactive (fsi) I guess I subconsciously knew it, but never paid attention to it.

Now that it is apparent, why the difference?

More specifically please explain how the internals are different between fsi and the compiler such that this occurs by design or result of differences?

If the answer can elaborate on the internal structures that hold the bindings that would be appreciated.

like image 282
Guy Coder Avatar asked Dec 02 '13 11:12

Guy Coder


People also ask

What does f stand for in math?

more ... A special relationship where each input has a single output. It is often written as "f(x)" where x is the input value. Example: f(x) = x/2 ("f of x equals x divided by 2")

What is f apostrophe?

The derivative of f(x) is written using an apostrophe after the f. The notation is f´(x) or y´ The notation dy/dx is also commonly used. First look at the constant function, or f(x) = k where k is a constant value, for example f(x) = 2 or y = 2 The graph is shown here.

What is the formula of f x?

The slope of a linear function is calculated by rearranging the equation to its general form, f(x) = mx + c; where m is the slope. The vertex of a quadratic function is calculated by rearranging the equation to its general form, f(x) = a(x – h)2 + k; where (h, k) is the vertex.

Does Y equal FX?

Remember: The notation "f (x)" is exactly the same thing as "y". You can even label the y-axis on your graphs with "f (x)", if you feel like it.


1 Answers

The semantics are consistent with the way FSI compiles interactive submissions to an FSI session: each interactive submission is compiled as module which is open to subsequent interactive submissions.

The following is close to what FSI actual does and illustrates how let binding shadowing works across interactive submissions:

FSI Submission #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 Submission #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

You can see the actual details how how the dynamic FSI assembly is compiled by using reflection on the FSI_ASSEMBLY assembly within the FSI app domain. Each interactive submission is literally emitted as a module (.NET class) with the naming pattern FSI_####. FsEye uses these facts to discover the state of FSI top-level bindings: https://code.google.com/p/fseye/source/browse/tags/2.0.1/FsEye/Fsi/SessionQueries.fs#24

The key takeaway in regard to @JohnPalmer's answer is that top-level FSI definitions cannot be mutated, when they are "redefined" they are merely being shadowed. We can show this as follows:

> 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
like image 117
Stephen Swensen Avatar answered Sep 23 '22 16:09

Stephen Swensen