#f# #coding-style #global-variables
#f# #стиль кодирования #глобальные переменные
Вопрос:
Для проекта, над которым я работаю, мне нужна глобальная переменная (технически у меня ее нет, я мог бы создать ее, а затем передавать в каждый отдельный вызов функции и сообщать об этом каждому отдельному вызову функции, но это кажется таким же халтурным, менее читаемым и более трудоемким.)
Глобальными переменными являются таблицы поиска (эндшпиль, вступительная книга и транспозиции / кэш) для игры.
Тот факт, что часть кода может потерять часть своего независимого поведения, на самом деле является точкой (ускорения) короче говоря, да, я знаю, что глобальное изменяемое состояние плохое, в данном случае это действительно того стоит (повышение производительности в 10 раз )
Итак, вот вопрос: «создайте синглтон или используйте статическое значение в статическом классе с комбинаторами»
Они фактически идентичны, но мне любопытно, что люди делали раньше с такого рода проблемами
Или, в качестве альтернативы, я должен передавать эту вещь всем (или, по крайней мере, ссылку на нее в любом случае), это действительно лучший ответ?
Ответ №1:
Вот решение, аналогичное тому, которое опубликовал @Yin Zhu, но использующее абстрактные типы для указания интерфейса использования для изменяемого значения, локальное определение для его инкапсуляции и объектные литералы для обеспечения реализации (это взято из Expert F #, соавтором которого является Дон Сайм):
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 }
Ответ №2:
Вы также можете сделать это со статическими полями, например, так:
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
Ответ №3:
вот соглашение, используемое в матричной библиотеке F # PowerPack ( srcFSharp.PowerPackmathassociations.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))
Комментарии:
1. Я несколько раз видел, как люди создавали модуль с общедоступными ссылочными типами. Я не уверен, какая из них «более рекомендуется», вероятно, это зависит от того, экспортируете ли вы позже в other . Чистый язык или нет.