有没有办法在保持流畅的管道语法的同时执行比较?
例如,我想这样做:
(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
附录
[<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...
答案 0 :(得分:6)
@ildjarn在评论中发布的解决方案是您问题的答案。
但是,我个人不会这样做。当您对捕获代码的主要数据的某些内容执行一系列转换时,管道非常有用。管道有一个输入和一个输出这个事实很好地捕获了这个:
let output =
input
|> firstTransformation
|> secondTransformation
Pipe可以在许多其他场景中使用(毕竟,它只是一个操作符),但我认为在其他场景中使用它并不会使F#代码更具可读性。将管道仅用于&#34;主要数据&#34;是快速浏览一下代码,了解重要操作的位置。
这也是我对||>
不太热衷的部分原因 - 它有助于fold
的类型推断,但除此之外,它给人的假象是函数有一个&#34 ;主要输入&#34;事实上,它需要多个同样重要的投入。所以在你的例子中,我会写:
let updatedPositions = jump target positions source
updatedPositions.Length = positions.Length ||
updatedPositions.Length = positions.Length - 1
我认为这更好地对应于代码背后的逻辑 - 将两件事传递给jump
并检查结果的两个属性 - 而不是以下管道版本:
(positions, source)
||> jump target
|> fun updatedPositions ->
updatedPositions.Length = positions.Length ||
updatedPositions.Length = positions.Length - 1
let
的版本更短,更直接。在阅读第二篇文章时,你必须解开很多东西来弄清楚发生了什么。
答案 1 :(得分:1)
对于代码高尔夫答案,如果要避免使用显式lambda函数:
如果您从Haskell flip
定义let inline flip f a b = f b a
运算符,那么您可以执行|> List.length |> flip List.contains [positions.Length; positions.Length - 1]
。
您可以通过将其定义为实际操作符来使其更加漂亮,以便它看起来像占位符:let inline (--) f a b = f b a
然后您可以执行|> List.length |> (List.contains -- [positions.Length; positions.Length - 1])
或者您可以使用https://github.com/fsprojects/FSharp.Core.Fluent来简化它,它只会变成|> List.length |> [positions.Length; positions.Length - 1].contains
我不会为生产代码做任何这些。