在 f# 中格式化复合函数

formatting Composite function in f#

我在 f# 中有一个递归函数,它迭代需要 运行 的命令的字符串 [],每个命令 运行s 一个新命令来生成要传递给下一个的映射功能。

命令 运行 正确但又大又难读,我相信有更好的方法来使用管道语法来排序/格式化这些复合函数,但是来自 c#,就像我们很多人一样因为我的生活似乎无法让它发挥作用。

我的命令是:

 let rec iterateCommands (map:Map<int,string array>) commandPosition  = 
    if commandPosition < commands.Length then
        match splitCommand(commands.[0]).[0] with
        |"comOne" -> 
           iterateCommands (map.Add(commandPosition,create(splitCommand commands.[commandPosition])))(commandPosition+1)

我最接近的方法是缩进函数,但这很混乱:

iterateCommands 
(map.Add
    (commandPosition,create
        (splitCommand commands.[commandPosition])
    )
) 
(commandPosition+1)

甚至可以在 f# 中重新格式化吗?根据我的阅读,我相信这是可能的,任何帮助将不胜感激

The command/variable types are:
commandPosition - int
commands - string[]
splitCommand string -> string[]
create string[] -> string[]
map : Map<int,string[]>

当然还有 map.add 地图 -> 地图 + x

通常很难弄清包含多个输入的大语句中发生了什么。我会给各个表达式命名,这样 reader 就可以跳到任何位置并大致了解计算中使用的值是什么,例如

let inCommands = splitCommand commands.[commandPosition]
let map' = map.Add (commandPosition, inCommands)
iterateCommands map' inCommands

由于我不知道这里是做什么的,所以这些名字意义不大。理想情况下,它们有助于理解计算的各个步骤。

如果您更改周围的参数,编写调用会更容易一些:

let rec iterateCommands commandPosition (map:Map<int,string array>) =
    // ...

这将使您能够编写如下内容:

splitCommand commands.[commandPosition]
|> create
|> (fun x -> commandPosition, x)
|> map.Add
|> iterateCommands (commandPosition + 1)

在我看来,commandPosition 在组合中 三次 出现的事实是一种设计气味,因为整个表达式的类型是unit。它看起来不是特别实用,但由于我不完全理解这个功能试图做什么,所以我不能建议更好的设计。

如果您无法控制 iterateCommands,因此无法更改参数的顺序,您始终可以定义一个标准的函数式编程实用函数:

let flip f x y = f y x

这使您能够针对 iterateCommands 的原始版本编写以下内容:

splitCommand commands.[commandPosition]
|> create
|> (fun x -> commandPosition, x)
|> map.Add
|> (flip iterateCommands) (commandPosition + 1)