Вероятно, вы можете реализовать это с помощью .NET Reflection - локальные переменные и функции определяются как статические свойства / методы типов в одной динамической сборке.Вы можете получить эту сборку, вызвав GetExecutingAssembly
(в самом FSI), а затем просмотрите типы, чтобы найти все подходящие свойства.
Ниже приводится разумно работающая функция для получения локальных переменных:
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
Вот пример:
> 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
Функция возвращает «ленивое» значение обратно (потому что это был самый простой способ записать его без предварительного чтения значений всех переменных, которыебудет медленным), поэтому вам нужно использовать свойство Value
.Также обратите внимание, что вы получаете object
назад - потому что система типа F # не может знать тип - вам придется использовать его динамически.Вы можете получить все имена, просто перебрав vars
...