F#管道占位符?

时间:2014-02-14 12:38:30

标签: f# pipeline pipelining

我有点googlet,我还没找到我想要的东西。正如所料。我的问题是,是否可以定义一个F#管道占位符?我想要的是如下_中的_:

let func a b c = 2*a + 3*b + c

2 |> func 5 _ 6

评估为22(2 * 5 + 3 * 2 + 6)。

为了进行比较,请查看magrittr R套餐:https://github.com/smbache/magrittr

6 个答案:

答案 0 :(得分:6)

这是(不幸的是!)F#语言不支持 - 虽然您可以想出各种花哨的函数和运算符来模拟行为,但我认为重构代码通常更容易,因此调用不在管道。然后你可以写:

let input = 2
let result = func 5 input 6

管道的优势在于您有一个“主”数据结构,该结构通过一系列步骤处理(例如通过一系列List.xyz函数处理的列表)。在这种情况下,管道使代码更好,更易读。

但是,如果您的函数需要多个输入而没有“主”输入(最后一个参数可以使用管道),那么使用临时变量和普通函数调用实际上更具可读性。

答案 1 :(得分:2)

我不认为这是可能的,但你可以简单地使用lambda表达式,比如

2 |> (fun b -> func 5 b 6)

答案 2 :(得分:1)

你可以使用这样的新功能:

let func a b c = 2*a + 3*b + c
let func2 b = func 5 b 6

2 |> func2

答案 3 :(得分:1)

这是一种无点的方法:

let func a b c = 2*a + 3*b + c
let func' = func 5 >> (|>) 6
let result = 2 |> func'
// result = 22

我已经详细解释了here

但请注意,使用您的代码的人不会很快掌握您的意图。您可以将它用于学习语言的更深层次的目的,但在实际项目中,您可能会找到更适合的简单方法:

let func' b = func 5 b 6

答案 4 :(得分:0)

@Dominic Kexel对钱的权利。如果对象实际上不是在参数链中放置占位符,这可能是由lambda函数实现的,但是改变了它们的顺序,那么flip的情况就比pipe更多。 。

从简单的两参数案例

let flip f b a = f a b
// val flip : f:('a -> 'b -> 'c) -> b:'b -> a:'a -> 'c

我们需要派生一个函数

let flip23of3 f a c b = f a b c
// val flip23of3 : f:('a -> 'b -> 'c -> 'd) -> a:'a -> c:'c -> b:'b -> 'd

为了翻转第二个和第三个参数。这也可以写成

let flip23of3' f = f >> flip

let func a b c = 2*a + 3*b + c
2 |> flip23of3 func 5 6
// val it : int = 22

答案 5 :(得分:-1)

我自己试一试。结果并不完美,但它和我一样接近:

let (|.|) (x: 'a -> 'b -> 'c) (y: 'b) = fun (a: 'a) -> x a y

let func (a:string) b (c:int) = 2.*(float a) + b + 5.*(float c)

let foo = func "4" 9. 5
printfn "First: %f" foo

let bar =
    "4"
    |> ((func |.| 9.) |.| 5)

printfn "Second: %f" bar

let baz =
    9.
    |> (func "4" |.| 5)
printfn "Third: %f" baz

输出正如预期的那样

First: 42.000000
Second: 42.000000
Third: 42.000000