格式化f#中的复合函数

时间:2016-04-11 13:38:59

标签: f# code-formatting

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

这些命令运行正常,但是读起来很大而且很麻烦,我相信有一种更好的方法可以使用管道语法对这些复合函数进行排序/格式化然而来自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地图 - &gt; map + x

2 个答案:

答案 0 :(得分:3)

通常很难弄清楚多个输入的大型声明中发生了什么。我给各个表达式命名,以便读者可以跳到任何位置并大致了解计算中使用的值,例如。

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

由于我不知道这里做了什么,这些名字并没有多大意义。理想情况下,他们有助于理解计算的各个步骤。

答案 1 :(得分:2)

如果更改了参数,那么编写调用会更容易:

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)