Этот вопрос относится к вопросу и совпадает с вопросом в Должен ли один провайдер типа переноса содержать значения, которые имеют побочные эффекты внутри класса? , любезно ответил Aaron M. Eshbach
.
Iя пытаюсь реализовать в своем коде отличный совет на странице F# coding conventions
https://docs.microsoft.com/en-us/dotnet/fsharp/style-guide/conventions.
Раздел Use classes to contain values that have side effects
особенно интересен.Там написано
There are many times when initializing a value can have side effects, such as instantiating a context to a database or other remote resource. It is tempting to initialize such things in a module and use it in subsequent functions.
и приведен пример.Затем он указывает на три проблемы с этой практикой (я пропускаю их из-за недостатка места, но их можно увидеть в связанной статье) и рекомендует использовать простой класс для хранения зависимостей.
Следуя этому совету, который я реализовалпростой класс, содержащий значение с побочными эффектами:
type Roots() =
let msg = "Roots: Computer must be one of THREADRIPPER, LAPTOP or HPW8"
member this.dropboxRoot =
let computerName = Environment.MachineName
match computerName with
| "THREADRIPPER" -> @"C:\"
| "HP-LAPTOP" -> @"C:\"
| "HPW8" -> @"H:\"
| _ -> failwith msg
Тогда я могу использовать его внутри функции
let foo (name: string) =
let roots = Roots()
let path = Path.Combine(roots.dropboxRoot, @"Dropbox\Temp\" + name + ".csv")
printfn "%s" path
foo "SomeName"
Пока все хорошо.В приведенном выше примере класс довольно «легкий», и я могу создать его экземпляр внутри любой функции.
Тем не менее, класс, содержащий значения с побочными эффектами, также может быть вычислительно интенсивным.В этом случае я хотел бы создать его экземпляр только один раз и вызвать его из разных функций:
let roots = Roots()
let csvPrinter (name: string) =
let path = Path.Combine(roots.dropboxRoot, @"Dropbox\Folder1\" + name + ".csv")
printfn "%s" path
let xlsxPrinter (name: string) =
let path = Path.Combine(roots.dropboxRoot, @"Dropbox\Folder2\" + name + ".xlsx")
printfn "%s" path
csvPrinter "SomeName"
xlsxPrinter "AnotherName"
Поэтому мой вопрос: если я создаю экземпляр класса Roots
на верхнем уровне в модуле, я побеждаюцель создания класса, чтобы избежать проблем, описанных на странице F# coding conventions
?Если это так, то как мне работать с вычислительно-интенсивными определениями?