Sna*_*ark 6 f# coding-style global-variables
对于我正在研究的项目,我需要一个全局变量(技术上我没有,我可以构建它然后将它传递给每个函数调用,让每个函数调用都知道它,但这看起来像hacky,不太可读和更多的工作.)
全局变量是游戏的查找表(最后阶段,开始书和转置/缓存).
事实上,一些代码可能会失去一些不负责任的行为,实际上就是简单(加速),是的,我知道全局可变状态很糟糕,在这种情况下它确实值得(10x +性能提升)
所以这里的问题是"在一个带有组合器的静态类中构建单例或使用静态值"
它们实际上完全相同,但我很好奇人们之前在这类问题上所做的事情
或者,如果我将这个东西传递给每个人(或者至少是对它的引用),那真的是最好的答案吗?
这是一个与@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)
以下是 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)