我应该在 F# 中使用子函数还是辅助函数?

Should I go for subfunctions or helper functions in F#?

我正在用 F# 编写一个性能至关重要的大型项目。目前的核心结构是 19 个函数,所有函数都具有相同的签名:参数 -> 记录 -> 结果(记录,错误)和适当的 composition/binding 这些确保前一个函数产生的记录在下一个。参数永远不会被覆盖,因此它们在所有 19 个函数调用中都是相同的。这里是“最终”功能:

let execution parameters record = 
let (>==) m f = Result.bind (f parameters) m

record
|> stepOne parameters
>== stepTwo
>== stepThree

我的问题是:就性能(或风格)而言,将步骤定义为类型为 record -> record 的“执行”的子函数是否更好,这样就不必传递相同的参数 19多次通过不同的功能? 它还允许代码依赖于特定参数(参数是记录类型)而不是一次依赖所有参数。另一方面,这些子函数不能在这个上下文之外重用(我不认为,他们永远会),这可能会使单元测试更加困难。在我的例子中,这也意味着一个非常长的执行函数,这可能是不可取的。非常感谢任何输入!

"在性能(或风格)方面,将步骤定义为类型为 record -> record 的"execution"的子函数会不会更好,这样相同的参数就不必通过不同的方法传递 19 次功能?

当然可以。就那样写,然后 profile 它。

更一般:

进入良好的 F# 编程风格需要一点时间,阅读书籍或良好的代码存储库有助于实现这一目标。

您的代码使用“面向铁路的编程”,Scott Wlaschin 的最佳解释:https://fsharpforfunandprofit.com/rop/

这种编程风格很好,但肯定不适合高性能循环。但即使在对性能高度敏感的程序中,也只有 5% 的代码处于高性能循环中。所以漂亮的设计模式有很大的空间。优化核心性能代码只能针对具体案例进行。技术首先是 try and profile。如果您提到的代码确实在性能关键路径中,那么您的测量将表明避免函数调用和参数传递会导致更快的代码。