有没有办法在保持流畅的管道语法的同时执行比较?

Sco*_*rod 0 f#

有没有办法在保持流畅的管道语法的同时执行比较?

例如,我想这样做:

(positions , source) ||> jump target
                      |> List.length = positions.Length || 
                                       positions.Length - 1
Run Code Online (Sandbox Code Playgroud)

但相反,我觉得我必须这样做:

let updatedPositions = (positions , source) ||> jump target
// Return result
updatedPositions |> List.length = positions.Length       || 
updatedPositions |> List.length = positions.Length - 1
Run Code Online (Sandbox Code Playgroud)

附录:

[<Property(QuietOnSuccess = true, MaxTest=1000)>]
let ``Attempted checker jump results in zero or one distinct checkers removed`` () =

    // Setup
    gen {
        let! source =          Arb.generate<Piece>
        let! target =          Arb.generate<Piece>
        let! otherPositions =  Arb.generate<Space list>
        let! positions =       Occupied source :: Occupied target
                                               :: otherPositions 
                                               |> Gen.shuffle

        return source , target, positions |> Seq.distinct
                                          |> Seq.toList }
    |> Arb.fromGen

    // Test
    |> Prop.forAll 
    <| fun (source , target, positions) -> 
        (positions , source) ||> jump target
                              |> List.length = positions.Length ||
                                 List.length = positions.Length - 1 // Wish I could do this...
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 6

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

但是,我个人不会这样做.当您对捕获"代码的主要数据"的内容执行一系列转换时,管道非常有用.管道有一个输入和一个输出,这很好地捕获了这个:

let output = 
  input 
  |> firstTransformation
  |> secondTransformation
Run Code Online (Sandbox Code Playgroud)

Pipe可以在许多其他场景中使用(毕竟,它只是一个运算符),但我认为在其他场景中使用它并不会使F#代码更具可读性.将管道仅用于"主要数据"的好处是,快速浏览一下代码可以显示重要操作的位置.

这也是我不太热衷的部分原因||>- 它有助于类型推断,fold但除此之外,它给人一种假象,即当一个函数实际上需要多个同等重要的输入时,它有一个"主输入".所以在你的例子中,我会写:

let updatedPositions = jump target positions source
updatedPositions.Length = positions.Length || 
  updatedPositions.Length = positions.Length - 1
Run Code Online (Sandbox Code Playgroud)

我认为这更好地对应于代码背后的逻辑 - 传递两个东西jump并检查结果的两个属性 - 而不是以下管道版本:

(positions, source) 
||> jump target
|> fun updatedPositions -> 
     updatedPositions.Length = positions.Length ||
     updatedPositions.Length = positions.Length - 1
Run Code Online (Sandbox Code Playgroud)

版本let更短,更简单.阅读第二篇文章时,你必须解压得很多才能弄清楚发生了什么.

  • 抱歉.我喜欢滥用我最近学到的概念.=) (3认同)