我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
我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
F# 语言不支持(不幸的是!) - 虽然您可以提出各种花哨的函数和运算符来模拟行为,但我认为重构代码通常更容易,以便调用在管道之外。然后你可以写:
let input = 2
let result = func 5 input 6
管道的优势在于您拥有一个通过一系列步骤处理的“主要”数据结构(例如通过一系列List.xyz
函数处理的列表)。在这种情况下,管道使代码更美观、更易读。
但是,如果您的函数接受多个输入并且没有“主”输入(可用于管道的最后一个参数),那么使用临时变量和普通函数调用实际上更具可读性。
我认为这是不可能的,但你可以简单地使用 lambda 表达式,比如
2 |> (fun b -> func 5 b 6)
这是一个无点的方法:
let func a b c = 2*a + 3*b + c
let func' = func 5 >> (|>) 6
let result = 2 |> func'
// result = 22
我已经在这里详细解释了。
但是请注意,使用您的代码的人不会很快掌握您的意图。您可以使用它来学习语言的更深层次,但在实际项目中,您可能会发现一种更适合的简单方法:
let func' b = func 5 b 6
您可以使用这样的新功能:
let func a b c = 2*a + 3*b + c
let func2 b = func 5 b 6
2 |> func2
@Dominic Kexel 是正确的。如果对象实际上不是在参数链中放置占位符,这可以通过 lambda 函数实现,但改变它们的顺序,那么它更像是flip
than 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
我自己试了一下。结果并不完美,但它与我得到的一样接近:
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