F# interactive - how to see all the variables defi

2020-02-20 03:03发布

问题:

In F# interactive, how can I see a list of variables/functions defined in this session? Like a function whos() in python or ls() in R? Thanks.

回答1:

You can probably implement this using .NET Reflection - local variables and functions are defined as static properties/methods of types in a single dynamic assembly. You can get that assembly by calling GetExecutingAssembly (in FSI itself) and then browse the types to find all suitable properties.

The following is a reasonably working function for getting local variables:

open System.Reflection
open System.Collections.Generic

let getVariables() = 
  let types = Assembly.GetExecutingAssembly().GetTypes()
  [ for t in types |> Seq.sortBy (fun t -> t.Name) do
      if t.Name.StartsWith("FSI_") then 
        let flags = BindingFlags.Static ||| BindingFlags.NonPublic |||
                    BindingFlags.Public
        for m in t.GetProperties(flags) do 
          yield m.Name, lazy m.GetValue(null, [||]) ] |> dict

Here is an example:

> let test1 = "Hello world";;
val test1 : string = "Hello world"

> let test2 = 42;;
val test2 : int = 42

> let vars = getVariables();;
val vars : System.Collections.Generic.IDictionary<string,Lazy<obj>>

> vars.["test1"].Value;;
val it : obj = "Hello world"

> vars.["test2"].Value;;
val it : obj = 42

The function returns "lazy" value back (because this was the simplest way to write it without reading values of all variables in advance which would be slow), so you need to use the Value property. Also note that you get object back - because there is no way the F# type system could know the type - you'll have to use it dynamically. You can get all names just by iterating over vars...



回答2:

I'm developing FsEye, which uses a modified version of @Tomas' technique (filters out unit and function valued vars and only takes the latest it var) to grab all FSI session variables upon each submission and displays them visually in a tree so that you can drill down into their object graphs.

You can see my modified version here.



回答3:

Unfortunately there is no way to do this in FSI at this stage.