F#:用括号括号调用函数是否是惯用的方法?

时间:2015-10-18 10:24:36

标签: f#

如果有这样的功能:

let test arg func =
    func arg

使用管道来调用它是否是惯用的方式

test 1 <| fun n -> n = 2

而不是用括号来调用它?

test 1 (fun n -> n = 2)

当一个人不应该以这种方式使用烟斗?

3 个答案:

答案 0 :(得分:5)

TL;博士

在我看来,这很好:

test 1 (fun n -> n = 2)

由于参数的顺序,它可能不会很好地组成,所以进一步的细节如下。如果您需要,可以使用这些选项。

详细

我认为翻转test函数的参数更为惯用:

let test' func arg = func arg

因为这样可以改为编写这个表达式:

1 |> test' (fun n -> n = 2)

如果您无法更改test的签名,可以介绍a flip function

let flip f x y = f y x

此函数翻转函数的参数,以便您可以改为编写:

1 |> (flip test) (fun n -> n = 2)

在这里给出的例子中,这使得事情变得比以前更复杂,所以我更倾向于选择原始建议之一:

test 1 (fun n -> n = 2)

就我个人而言,我发现比向后管道更容易理解,这总是让我感到困惑。

顺便说一下,您可以在此特定示例中减少功能:

test 1 ((=) 2)

答案 1 :(得分:3)

This snippet之前的{p> Stephen Swensen演示了高优先级,右关联反向管道(^<|)

let inline (^<|) f a = f a

链接页面中的这个单行演示了如何使用它:

{1..10} |> Seq.map ^<| fun x -> x + 3

以下是如何将其用于多行功能的示例。我发现它对于真实世界的多线程最有用,因为你不再需要在最后保持右括号:

myCommands
|> List.map ^<| fun command ->
    let returnValue = manipulate command
    doSomethingElse()
    returnValue

另一个好处是保持参数的自然顺序,这通常可以帮助您避免额外的类型注释。在上面的代码段中,command的类型会自动推断。

答案 2 :(得分:2)

我不认为对一方有强烈的偏好。

就我个人而言,我个人使用parens作为单行代码:

test 1 (fun n -> n = 2)
如果func有多条线路,那么

和管道 - 这样你就不需要在改变功能体时需要移动的笨拙的关闭按钮:

test 1 <| fun n -> 
    let x = n + 1
    x = 3