gpt4 book ai didi

f# - 管还是不管?

转载 作者:行者123 更新时间:2023-12-04 22:54:52 26 4
gpt4 key购买 nike

那是(某种)问题。

我最近正在尝试更多地学习 F#,而我的资源似乎更喜欢在不清楚是否存在好处的地方进行管道。例如,给定一个柯里化(Currying)形式的函数:
f: a -> b -> c -> R
我可以通过提供所有内联或管道参数来调用它 c像这样:

let r = f a b c 
let r = c |> f a b

但有成本或 yield ,还是纯粹是风格偏好?

最佳答案

应该没有成本。

更新

可能是 一些额外的费用。
有时会插入额外的调用,但有时编译器可以对其进行优化以避免额外的调用。

我测试了以下代码:

let concat (a:string) (b:string) = System.String.Concat(a, b)

let f1 g a c = g a c
let f2 g a c = c |> g a

f1 concat "b" "c" \\ 00:00:33.8895616
f2 concat "b" "c" \\ 00:00:34.6051700
concat "b" "c" \\ 00:00:35.0669532
"c" |> concat "b" \\ 00:00:35.1948296
f1 (+) "b" "c" \\ 00:00:35.4796687
f2 (+) "b" "c" \\ 00:00:49.3227193
(+) "b" "c" \\ 00:00:35.0689207
"c" |> (+) "b" \\ 00:00:35.8214733

对于每种情况,我执行了 10 亿次调用 ( 1_000_000_000),那是时代。如您所见,仅调用 f2 (+) "b" "c"比其他的慢,这可能与 (+) 是使用 SRTP 的运算符有关。

感谢@PhillipCarter 的澄清。

管道的使用有助于类型推断:
let words = "many words".Split ' '

let wordsU1 = words |> Array.map (fun w -> w.ToUpper()) // ok
wordsU1 |> Seq.iter (printfn "words are %A")

let wordsU2 = Array.map (fun w -> w.ToUpper()) words // type annotation needed: (w:string)
Seq.iter (printfn "words are %A") wordsU2

两次调用 Array.map是等价的,但第二个提示它不知道 w 的类型.这是因为 F# 类型推理机制从左到右工作,在第二种情况下 words在 lambda 函数之后。

它在风格上也更好。上面的代码可以这样更好地表达:
"many words".Split ' '
|> Array.map (fun w -> w.ToUpper())
|> Seq.iter (printfn "words are %A")

因此,管道可用于链接多个表达式,而无需使用括号或将其绑定(bind)到名称。

关于f# - 管还是不管?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53797690/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com