我想计算依赖于某些变量(运行代码的特定数据)和全局变量的函数,这些变量不太可能被更改,但我想让它们可供用户调整。只是为了举例说明,假设我要声明以下函数:
let multiplyByGain x =
x * gain
您将在哪里声明收益,即在整个项目中取得全局常数。在带有常量的单独模块中?但是,这会将模块与该代码耦合在一起。还是使用咖喱版本:
let multiblyByGain x gain =
x * gain
然后专门研究特定值?但是假设您有许多这样的功能,您将不得不为所有这些功能注入收益(在一种链接模块中)?
在我的特定问题中,这变得更加麻烦,因为x和gain都是必须具有相同长度的数组,假设我必须执行Array.zip,例如:在函数设计方面,解决全局问题的最佳实践是什么常数,一般来说是增益?
P.S .:我发现了这个旧帖子enter link description here,但仅解决了一个特定问题。
没有单个正确的答案,最佳方法将取决于您的其他各种约束和要求。同样,这取决于您是否专门询问F#还是更一般地询问函数编程。我认为有三个要点:
保持简单。使用将gain
公开为全局值的模块,该模块具有一些用于读取配置的初始化代码,这似乎是F#中的一种很好的默认方法。如果只有很少的更改(例如,在运行整个计算之前),则更改不会给您带来任何麻烦。您只需要注意避免在某些计算仍在运行时更改值。我认为大多数F#程序员对此都比较务实,这似乎是最简单的开始。
单元测试。如果要使用不同的multiplyByGain
作为参数对gain
函数进行单元测试,则需要某种方法将单元测试中的gain
的不同值传递给该函数。在这种情况下,将其作为附加参数并使用currying很好,因为您可以使用测试中的其他gain
值来调用它。
功能编程。一些功能语言社区(尤其是Haskell,有时还包括Scala)对状态的要求更加严格。保持状态的纯功能方式是使用monad(读者monad或某种自由monad结构)。这使您的代码复杂得多(无论从概念上还是从额外的语法开销上来说),但这只是一种消除状态的纯功能性解决方案。在F#中,这种方法更加麻烦,因此不是很常见。