F#中全局变量的样式指南

Sna*_*ark 6 f# coding-style global-variables

对于我正在研究的项目,我需要一个全局变量(技术上我没有,我可以构建它然后将它传递给每个函数调用,让每个函数调用都知道它,但这看起来像hacky,不太可读和更多的工作.)

全局变量是游戏的查找表(最后阶段,开始书和转置/缓存).

事实上,一些代码可能会失去一些不负责任的行为,实际上就是简单(加速),是的,我知道全局可变状态很糟糕,在这种情况下它确实值得(10x +性能提升)

所以这里的问题是"在一个带有组合器的静态类中构建单例或使用静态值"

它们实际上完全相同,但我很好奇人们之前在这类问题上所做的事情

或者,如果我将这个东西传递给每个人(或者至少是对它的引用),那真的是最好的答案吗?

Ale*_*lex 5

这是一个与@Yin Zhu 发布的解决方案类似的解决方案,但使用抽象类型来指定可变值的使用接口,使用本地定义来封装它,并使用对象文字来提供实现(这取自 Expert F#--由唐·赛姆 (Don Syme) 合着):

type IPeekPoke =
    abstract member Peek: unit -> int
    abstract member Poke: int -> unit

let makeCounter initialState =
    let state = ref initialState
    { new IPeekPoke with
        member x.Poke(n) = state := !state + n
        member x.Peek() = !state }
Run Code Online (Sandbox Code Playgroud)


Yin*_*Zhu 2

以下是 F# PowerPack Matrix 库中使用的约定 ( \src\FSharp.PowerPackmath\associations.fs):

// put global variable in a special module
module GlobalAssociations =
    // global variable ht
    let ht = 
        let ht = new System.Collections.Generic.Dictionary<Type,obj>() 
        let optab =
            [ typeof<float>,   (Some(FloatNumerics    :> INumeric<float>) :> obj);
              typeof<int32>,   (Some(Int32Numerics    :> INumeric<int32>) :> obj);
                  ...
              typeof<bignum>,  (Some(BigRationalNumerics   :> INumeric<bignum>) :> obj); ]

        List.iter (fun (ty,ops) -> ht.Add(ty,ops)) optab;
        ht

    // method to update ht
    let Put (ty: System.Type, d : obj)  =
        // lock it before changing
        lock ht (fun () -> 
            if ht.ContainsKey(ty) then invalidArg "ty" ("the type "+ty.Name+" already has a registered numeric association");
            ht.Add(ty, d))
Run Code Online (Sandbox Code Playgroud)