let inline myfunction x y = ...
let inline mycurried = myfunction x // error, only functions may be marked inline
似乎不可能明确inline
curried函数。
因此,只要mycurried
被调用,即使inlined
myfunction
正确inlined
,它也不会得到{{1}},是否正确?
那么这可以被视为咖喱功能的缺点之一吗?
答案 0 :(得分:5)
我认为您的问题是point-free函数是否可以内联。
您发现的限制不是因为咖喱功能。 请注意,在您的示例中,curried函数位于右侧,在左侧,您具有无点函数。
F#只允许函数内联,而不是常量。
我原则你可能认为这可以被视为一个错误,因为类型推断足够聪明,可以发现这是一个(无点)函数,但是阅读Tomas关于副作用的注释。
显然,当编译器在左侧只找到一个标识符时,它会因此错误而失败:
let inline myfunction x y = x + y
let inline mycurried = myfunction 1
--> Only functions may be marked 'inline'
正如Brian所说,解决方法是在双方都添加一个明确的参数:
let inline mycurried x = (myfunction 1) x
但是你的功能不再是无点的,它与:
相同let inline mycurried x = myfunction 1 x
另一种方法可能是添加一个显式的通用参数:
let inline mycurried<'a> = myfunction 1
当通用参数明确显示在左侧时,它会编译。
我希望他们删除错误消息并将其发出警告,例如:
Since only functions can be 'inline' this value will be compiled as a function.
<强>更新强>
感谢Tomas的回答(和你的downvote)。
我个人认为这应该是一个警告,所以你知道你的代码的语义最终会改变,但是由你来决定做什么。
你说内联是“只是一个优化”但这并不完全正确:
。简单地内联所有功能并不能保证最佳代码。
。您可能希望使用静态约束,然后必须使用内联。
我希望能够定义我的(种类)通用常量,因为F#库已经存在(即:GenericZero和GenericOne)。我知道我的代码是纯粹的,所以我不在乎每次都执行它。
答案 1 :(得分:4)
我认为你只需要向双方添加一个显式参数(虽然我还没试过):
let inline myfunction x y = ...
let inline mycurried y = myfunction 42 y // or whatever value (42)
答案 2 :(得分:2)
编译器只允许inline
定义一个函数的let绑定。这与发生的事情基本相同with F# value restriction(并参见also here)。正如Brian所说,您可以通过向函数添加参数来轻松解决此问题。
为什么存在这种限制?如果它不存在,那么添加inline
会改变你的程序的含义,那会很糟糕!
例如,假设您有一个这样的函数(它创建可变状态并返回计数器函数):
let createCounter n =
let state = ref n
(fun () -> incr state; !state)
现在,以下代码:
let counter = createCounter 0
...创建一个可以多次使用的单个全局函数(调用counter()
),它将从1开始为您提供唯一的整数。如果您可以将其标记为inline
:
let inline counter = createCounter 0
...然后每次使用counter()
时,编译器都应将其替换为createCounter 0 ()
,因此每次调用计数器时都会得到1!