学习F#风格

时间:2014-08-29 09:34:05

标签: f# coding-style

当一个函数传递给另一个应该计算结果的函数然后将该值作为参数传递给另一个函数时,我发现我可以编写"以下代码有5种不同的方式。

let testnum testFun =
    testFun 4

printfn "result: %b" (testnum (=) 0)  

printfn "result: %b" <| testnum (<) 0

printfn "result: %b" (testnum <| (>=) 0)

testnum <|  (=) 0 |> printfn "result: %b"

printfn "resutl: %b" << testnum <| (<>) 0

我更喜欢没有括号的风格,但现在我想知道,假设我的目标是我的代码的可读性支持性,是否有首选风格?

2 个答案:

答案 0 :(得分:2)

对于你的例子,我会选择第一个:

printfn "result: %b" (testnum (=) 0) 

第二个是可以通过的:

printfn "result: %b" <| testnum (<) 0

其他人太做作了,他们看起来像混淆运动。

我在两种情况下只使用“向后”管道操作符:

  • 当我有一个需要嵌套括号的类型构造函数时,Some <| Foo ("bar", "baz")而不是Some (Foo ("bar", "baz"))

  • 当我想传递一个匿名函数作为最后一个参数时 - 它很好地传达了动作所在的位置:

    lock sync <| fun () ->
        ...
    

    值得一提的是,如果有多个匿名函数作为参数传递,我通常会将它们中的每一个括号括起来(值得注意的例外是当其中一个是一个字符长一个衬里而另一个有多行时 - 然后我仍然会使用上面的语法)。

对于流水线操作,我通常会使用|>来获取更长的流水线,并使用函数组合>>来获取更短的流水线,当我不需要在体内再次引用参数时功能。

我认为我不会将|><|放在同一行而不用括号中的一个。它看起来很奇怪。

答案 1 :(得分:1)

首选管|>,这有助推理和可读性

(=) 3 |> testnum |> printfn "result: %b"

你可以轻松地在多行上打破它

(=) 3
|> testnum
|> printfn "result: %b"

如果参数很少,你可以直接传递它们

testnum (=) 4 |> printfn "result: %b"

但使用管道|>或撰写>>(例如g x |> fx |> g |> f而非嵌套函数调用f(g(x)))更为惯用。这也有助于推理,例如代替.运算符

open System.Linq

let double x = x * 2

let double1 items = items |> Seq.map double
[1;2;3] |> double1 |> printfn "%A"

//this doesn't compile,
//error: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed ..
//
// let double2 items = items.Select(double)
// [1;2;3] |> double2 |> printfn "%A"

let double3 (items:seq<_>) = items.Select(double)
[1;2;3] |> double3 |> printfn "%A"

示例:https://dotnetfiddle.net/K0u3NQ