下面2个函数
let episodeDict1 (a: obj) =
match a with
| :? (Episode -> _) as generator ->
let episodes = [D; W; M]
let values = episodes |> List.map generator
List.zip episodes values
| :? _ as value -> [D, value; W, value; M, value]
|> dict |> Dictionary
let episodeDict2: obj -> Dictionary<Episode, _> = function
| :? (Episode -> _) as generator ->
let episodes = [D; W; M]
let values = episodes |> List.map generator
List.zip episodes values |> dict |> Dictionary
| :? _ as value -> [D, value; W, value; M, value] |> dict |> Dictionary
Run Code Online (Sandbox Code Playgroud)
做同样的事情,但是第二个不能被标记为内联
让内联episodeDict2...
FS0832 只有函数可以标记为“内联”
这看起来真的很奇怪。
有人可以解释一下吗?
在您的情况下,这两个函数实际上是等效的,因此编译器可以更智能并解决这个问题。然而,问题在于第二个函数被定义为“值”,而不是“语法函数”,即,它没有定义为let func x y z = ...。编译器使用简单的规则,仅允许内联语法函数。
这样做的原因是,当您有一个未定义为语法函数的函数时,可能无法内联它。例如:
let foo =
let mutable counter = 0
fun () -> counter <- counter + 1; counter
Run Code Online (Sandbox Code Playgroud)
如果您将这个定义的主体放在使用该函数的地方,它将改变程序的含义!例如foo () + foo ()return 3,但如果你天真地进行了内联:
( let mutable counter = 0
fun () -> counter <- counter + 1; counter ) () +
( let mutable counter = 0
fun () -> counter <- counter + 1; counter ) ()
Run Code Online (Sandbox Code Playgroud)
你会得到2这样的结果!同样,您可以想象更聪明的编译器来处理这个问题 - 但我相信这里的 F# 决定是合理的 - 有一个易于理解的简单规则(并确保您得到正确的东西)。