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

发布于 2024-11-07 22:31:14 字数 258 浏览 0 评论 0原文

我需要一个全局变量(我可以构建它,然后将其传递给每个函数调用,并让每个函数调用都知道它,但这似乎很老套,可读性较差,工作量也更大)。全局变量是游戏的查找表(残局:开局书和换位/缓存)。

某些代码可能会失去其幂等行为,这实际上是重点(加速)。我知道全局可变状态很糟糕,但这是值得的(10 倍以上的性能提升)。那么如何构建单例或在具有组合器的静态类中使用静态值呢?

它们实际上是相同的,但我很好奇人们在这类问题上做了什么。或者我应该把这个东西传递给每个人(或者至少是一个参考)?

I need a global variable (I could build it, then pass it to every single function call and let every single function call know about it, but that seems just as hacky, less readable and more work). The global variables are lookup tables (endgame: opening book and transpositions/cache) for a game.

That some of the code may lose its idempotent behavior is actually the point (speedups). I know global mutable state is bad but it's worth it (10x+ performance improvement). So how do I build a singleton or use a static value in a static class with combinators?

They are effectively identical but I am curious what people have done on this sort of problem. Or should I be passing the thing around to everyone (or at least a reference)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉生梦死 2024-11-14 22:31:14

这是一个类似于@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 }

Here is a solution similar to the one posted by @Yin Zhu's, but using abstract types to specify a usage interface for the mutable value, a local definition to encapsulate it and object literals to provide an implementation (this is taken from Expert F#--which is co-authored by 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 }
小糖芽 2024-11-14 22:31:14

您还可以使用静态字段来完成此操作,如下所示:

type Common() = 

    static let mutable queue : CloudQueue = null
    static let mutable storageAccount : CloudStorageAccount = null

    static member Queue 
        with get() = queue
        and set v = queue <- v
    static member StorageAccount 
        with get() = storageAccount
        and set v = storageAccount <- v

在另一个模块中,只需:

open Common
Common.Queue <- xxxx

You can also do it with static fields, like this:

type Common() = 

    static let mutable queue : CloudQueue = null
    static let mutable storageAccount : CloudStorageAccount = null

    static member Queue 
        with get() = queue
        and set v = queue <- v
    static member StorageAccount 
        with get() = storageAccount
        and set v = storageAccount <- v

In another module, just:

open Common
Common.Queue <- xxxx
泪眸﹌ 2024-11-14 22:31:14

以下是 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))

here is the convention used in F# PowerPack Matrix library (\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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文