F#“函数”函数无法内联

Fra*_*ron 0 f#

下面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 只有函数可以标记为“内联”

这看起来真的很奇怪。

有人可以解释一下吗?

Tom*_*cek 5

在您的情况下,这两个函数实际上是等效的,因此编译器可以更智能并解决这个问题。然而,问题在于第二个函数被定义为“值”,而不是“语法函数”,即,它没有定义为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# 决定是合理的 - 有一个易于理解的简单规则(并确保您得到正确的东西)。