F# 有没有一种方法可以在保持流畅的管道语法的同时执行比较?

F# 有没有一种方法可以在保持流畅的管道语法的同时执行比较?,f#,F#,有没有一种方法可以在保持流畅的管道语法的同时执行比较 例如,我想这样做: (positions , source) ||> jump target |> List.length = positions.Length || positions.Length - 1 let updatedPositions = (positions , source) ||>

有没有一种方法可以在保持流畅的管道语法的同时执行比较

例如,我想这样做:

(positions , source) ||> jump target
                      |> List.length = positions.Length || 
                                       positions.Length - 1
let updatedPositions = (positions , source) ||> jump target
// Return result
updatedPositions |> List.length = positions.Length       || 
updatedPositions |> List.length = positions.Length - 1
但是相反,我觉得我必须这样做:

(positions , source) ||> jump target
                      |> List.length = positions.Length || 
                                       positions.Length - 1
let updatedPositions = (positions , source) ||> jump target
// Return result
updatedPositions |> List.length = positions.Length       || 
updatedPositions |> List.length = positions.Length - 1
附件:


@ildjarn在评论中发布的解决方案就是您问题的答案

然而,我个人不会这样做。当您对捕获代码主要数据的内容执行一系列转换时,管道非常有用。管道有一个输入和一个输出这一事实很好地说明了这一点:

let output = 
  input 
  |> firstTransformation
  |> secondTransformation
毕竟,管道可以在许多其他场景中使用,它只是一个操作符,但我认为在其他场景中使用它并不能使F代码更具可读性。只对主数据使用管道的好处在于,快速浏览代码可以发现重要操作的位置

这也是我对| |>(fold)不太感兴趣的部分原因——它有助于fold的类型推断,但除此之外,它给人一种错误的印象,即一个函数只有一个主输入,而实际上它需要多个同样重要的输入。在你的例子中,我会写:

let updatedPositions = jump target positions source
updatedPositions.Length = positions.Length || 
  updatedPositions.Length = positions.Length - 1
我认为这比下面的管道版本更符合代码背后的逻辑——传递两个东西以跳转并检查关于结果的两个属性:

(positions, source) 
||> jump target
|> fun updatedPositions -> 
     updatedPositions.Length = positions.Length ||
     updatedPositions.Length = positions.Length - 1

使用let的版本更简短、更直接。在阅读第二篇文章时,您必须将大量内容解包以了解发生了什么。

对于代码高尔夫答案,如果您希望避免显式lambda函数:

如果从Haskell let inline flip f a b=f b a定义翻转运算符,则可以执行|>List.length |>flip List.contains[positions.length;positions.length-1]

通过将它定义为一个实际的运算符,使它看起来像一个占位符,您可以使它更漂亮:让inline-fab=fba然后您可以执行|>List.length |>List.contains-[positions.length;positions.length-1]

或者您可以通过使用简化它,它只会变成|>List.length |>[positions.length;positions.length-1]


但是,我不会对生产代码执行任何这些操作。

非常明显的|>fun l->l.Length=positions.Length | | l.Length=positions.Length-1有什么问题?很好的解决方案!你能把这个作为答案贴出来,这样我就可以相信你了吗?对我来说,这似乎不是一个“答案”,因为你已经在管道中使用了lambdas,所以这段代码似乎没有任何新概念…没有理由道歉:-。我认为这在很大程度上是风格或个人喜好的问题。我只是觉得我应该写一个答案,描述我将如何编写代码,并在后面进行更多的推理!|>List.length |>flip List.contains[positions.length;positions.length-1]正是我对生产代码所做的,只是它将是一个数组而不是List,flip将来自FSharpx。我看不出它有什么内在的问题。