6
let inline myfunction x y = ...

let inline mycurried = myfunction x // error, only functions may be marked inline

inline显式地柯里化函数似乎是不可能的。所以无论何时调用,即使正确mycurried也不会得到,对吗?inlinedmyfunctioninlined

那么这可以看作是柯里化函数的缺点之一吗?

4

3 回答 3

5

我认为您的问题是是否可以内联无点函数。

您发现的限制不是因为柯里化函数。请注意,在您的示例中,柯里化函数在右侧,在左侧,您有一个无点函数。

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)。我知道我的代码是纯粹的,所以我不在乎它是否每次都执行。

于 2012-09-21T09:58:26.683 回答
4

我认为您只需要在双方都添加一个显式参数(尽管我没有尝试过):

let inline myfunction x y = ... 

let inline mycurried y = myfunction 42 y  // or whatever value (42)
于 2012-09-20T22:43:41.843 回答
2

编译器只允许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!

于 2012-09-21T10:34:14.240 回答