为何F#中使用function定义的函数无法标记inline?
为什么用
function定义的F#函数无法标记inline? 先看两个功能完全一致的F#函数:
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
尝试给第二个函数添加inline修饰符时,会触发错误:
FS0832 Only functions may be marked 'inline'
原因解释
function是F#里的语法糖,本质等价于fun x -> match x with ...的lambda表达式。当你写成let episodeDict2: ... = function ...时,语法上是把一个lambda表达式赋值给一个绑定,而非直接定义一个带参数的函数。
而F#的inline修饰符有严格的语法限制:它只能直接作用于用let显式声明参数的函数定义(比如第一个函数let episodeDict1 (a: obj) = ...这种形式),不能用于赋值lambda表达式的绑定——哪怕这个绑定的类型是函数,语法上也不属于“直接定义的函数”范畴。
解决方法
如果要给这类函数添加inline,需要改成显式声明参数的形式,或者把function展开为带参数的fun表达式:
方式1:显式声明参数
let inline episodeDict2 (a: obj) : Dictionary<Episode, _> = match a with | :? (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
方式2:展开function为fun表达式
let inline episodeDict2: obj -> Dictionary<Episode, _> = fun a -> match a with | :? (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
这两种写法都符合inline的语法要求,可以正常编译。
内容的提问来源于stack exchange,提问作者Franco Tiveron
相关产品推荐
相关产品推荐

