2011-05-18 13 views
6

Para un proyecto en el que estoy trabajando Necesito una variable global (técnicamente no, podría compilarla y pasarla a cada llamada de función, y permitir que cada llamada de función sepa al respecto, pero parece tan hacky, menos legible y más trabajo.)Directrices de estilo para variables globales en F #

Las variables globales son tablas de búsqueda (final del juego, libro de apertura y transposiciones/caché) para un juego.

El hecho de que una parte del código puede perder parte de su comportamiento indempotent es en realidad el punto (aceleraciones) en resumen, sí sé estado mutable global es malo, es realmente vale la pena en este caso (10x + mejora del rendimiento)

Así que aquí está la pregunta: "construir un único o utilizar un valor estático en una clase estática con combinadores"

son efectivamente idéntica pero tengo curiosidad lo que se ha hecho antes en este tipo de problema

O, alternativamente, ¿debería pasarle la cosa a todos (o al menos a una referencia? de todos modos), ¿es realmente la mejor respuesta?

Respuesta

2

aquí es la convención utilizada en la biblioteca 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)) 
+0

que he visto en varias ocasiones la gente que crea un módulo con tipos árbitro públicas. No estoy seguro de cuál es "más recomendado", probablemente dependa de si exporta más tarde a otro lenguaje .Net o no. –

4

Aquí es una solución similar a la publicada por @Yin Zhu, pero el uso de tipos abstractos para especificar una interfaz de uso de la valor mutable, una definición local para encapsular y objetos literales para proporcionar una aplicación (esto es tomado de Expertos F # - que es co-escrito por 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 } 
3

también puede hacerlo con campos estáticos , como este:

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 

En otro módulo, simplemente:

open Common 
Common.Queue <- xxxx