let inline myfunction x y = ...
let inline mycurried = myfunction x // error, only functions may be marked inline
inline
显式地柯里化函数似乎是不可能的。所以无论何时调用,即使正确mycurried
也不会得到,对吗?inlined
myfunction
inlined
那么这可以看作是柯里化函数的缺点之一吗?
我认为您的问题是是否可以内联无点函数。
您发现的限制不是因为柯里化函数。请注意,在您的示例中,柯里化函数在右侧,在左侧,您有一个无点函数。
F# 只允许内联函数,而不是常量。
我原则上你可能认为这可以被认为是一个错误,因为类型推断足够聪明,可以发现这是一个(无点)函数,但请阅读 Tomas 关于副作用的注释。
显然,当编译器在左侧仅找到一个标识符时,它会因以下错误而失败:
let inline myfunction x y = x + y
let inline mycurried = myfunction 1
--> Only functions may be marked 'inline'
正如布赖恩所说,一种解决方法是在双方都添加一个显式参数:
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 的回答(以及您的反对票)。
我个人的观点是这应该是一个警告,所以你知道你的代码的语义最终会改变,但是接下来要由你来决定做什么。
您说内联“只是一种优化”,但这并不完全正确:
. 简单地将所有函数内联并不能保证最佳代码。
. 您可能想要使用静态约束,然后必须使用内联。
我希望能够定义我的(某种)泛型常量,就像 F# 库已经做的那样(即:GenericZero 和 GenericOne)。我知道我的代码是纯粹的,所以我不在乎它是否每次都执行。
我认为您只需要在双方都添加一个显式参数(尽管我没有尝试过):
let inline myfunction x y = ...
let inline mycurried y = myfunction 42 y // or whatever value (42)
编译器只允许inline
定义函数的 on let 绑定。这与 F# 值限制所发生的情况基本相同(另请参见此处)。正如布赖恩所说,您可以通过向函数添加参数来轻松解决此问题。
为什么会有这个限制?如果它不存在,那么添加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!