具有组合和管道功能的缩进

时间:2018-03-27 02:25:47

标签: f#

我正试图让这段代码正确,通过分成不同的行来让它可读,可以在这里使用一些帮助。

list |> Array.iter ( fun data -> data.Href |> ( regex.Match >> ( fun m ->
          let result = {ArticleModule.defaultArticle with publicationId = m.Groups.[1].Value; entityType = m.Groups.[3].Value; entityName = m.Groups.[4].Value; version = m.Groups.[5].Value}
) ) )

修改

最短的形式或许可以帮助进一步探讨如何在单独的行中打破这一点。

list |> Array.iter ( fun data -> data.Href |> ( regex.Match >> ( fun m -> Console.WriteLine m ) ) )

尝试1

list |> Array.iter (fun data -> (data.Href) 
     |> regex.Match // squiggly lines here
     |> (fun m -> Console.WriteLine m))

2 个答案:

答案 0 :(得分:3)

首先,既然你问如何缩进这段代码,我会指引你https://github.com/dungpa/fantomas/blob/master/docs/FormattingConventions.md,这是一个很好的参考,你应该书签。在该页面的3/4处你会发现https://github.com/dungpa/fantomas/blob/master/docs/FormattingConventions.md#pipeline-operators,这表明管道运算符的序列应该直接在流经管道的数据下用管道缩进:

let result =
    data
    |> step1
    |> Array.filter (fun x -> x == "something")
    |> step3

等等。

现在,将此建议应用于您的情况。

首先,您尝试1中的波浪线是因为在regex.Match线上,您仍然在fun data -> ... lambda内。 F#中的所有行都应该与它们所属的东西垂直排列(模糊的语言,因为这是适用于许多情况的一般规则)。在这里,这看起来像:

list |> Array.iter (fun data -> data.Href
                                |> regex.Match
                                |> (fun m -> Console.WriteLine m))

现在,这看起来对我来说很难看。所以我会将fun data -> ... lambda拆分成自己的函数:

let handleOneItem data =
    data.Href
    |> regex.Match
    |> (fun m -> Console.WriteLine m)

list |> Array.iter handleOneItem

好多了。

现在,让我们看一下您的原始代码,其中管道中的最终lambda没有调用Console.WriteLine,而是创建了一条记录。该代码中存在一个错误,即let语句本身不执行任何操作。你可能想写的是:

fun m ->
    let result = {ArticleModule.defaultArticle with publicationId = m.Groups.[1].Value; entityType = m.Groups.[3].Value; entityName = m.Groups.[4].Value; version = m.Groups.[5].Value}
    result

反过来可以简单地变成:

fun m ->
    {ArticleModule.defaultArticle with publicationId = m.Groups.[1].Value; entityType = m.Groups.[3].Value; entityName = m.Groups.[4].Value; version = m.Groups.[5].Value}

现在,我建议您删除这条长记录并将其拆分为多行(有关详细信息,请参阅https://github.com/dungpa/fantomas/blob/master/docs/FormattingConventions.md#records),如下所示:

fun m ->
    { ArticleModule.defaultArticle with
        publicationId = m.Groups.[1].Value
        entityType = m.Groups.[3].Value
        entityName = m.Groups.[4].Value
        version = m.Groups.[5].Value }

我可能会把它作为自己的命名函数:

let mkRecord m =
    { ArticleModule.defaultArticle with
        publicationId = m.Groups.[1].Value
        entityType = m.Groups.[3].Value
        entityName = m.Groups.[4].Value
        version = m.Groups.[5].Value }

现在让我们再看一下完整的代码:

let mkRecord m =
    { ArticleModule.defaultArticle with
        publicationId = m.Groups.[1].Value
        entityType = m.Groups.[3].Value
        entityName = m.Groups.[4].Value
        version = m.Groups.[5].Value }

let handleOneItem data =
    data.Href
    |> regex.Match
    |> mkRecord

list |> Array.iter handleOneItem

这里还有一个错误,那就是Array.iter是错误的类型。 Array.iter希望您提交一个返回unit的函数(即,不返回任何有意义的函数)。任何没有返回任何意义的函数显然都会被调用它的副作用,而不是它的返回值。由于mkRecord会返回一个值并且没有副作用,因此您需要Array.map。因此,代码的最终版本将是:

let mkRecord m =
    { ArticleModule.defaultArticle with
        publicationId = m.Groups.[1].Value
        entityType = m.Groups.[3].Value
        entityName = m.Groups.[4].Value
        version = m.Groups.[5].Value }

let handleOneItem data =
    data.Href
    |> regex.Match
    |> mkRecord

list |> Array.map handleOneItem

答案 1 :(得分:3)

使用for循环没有任何问题。如果你最后做的是一个必要的操作,比如打印到控制台,那么使用for循环清楚地表明这就是你所做的:

for data in list do
  let m = regex.Match data.Href
  Console.WriteLine m

在您的其他示例中,您似乎正在尝试使用Array.map来创建新数组。 @rmunn的答案很好地涵盖了这一点,但请注意,您不需要使用|>完成所有操作。使用let绑定通常更容易:

list |> Array.map (fun data ->
  let m = regex.Match data.Href
  { ArticleModule.defaultArticle with
      publicationId = m.Groups.[1].Value
      entityType = m.Groups.[3].Value
      entityName = m.Groups.[4].Value
      version = m.Groups.[5].Value })