F#中断超载不起作用

ozg*_*gur 3 f#

let (->>>) lst exp = for i in lst do exp

let result = [0..5] ->>> ([1..5] ->>> printf "hi")
let result2 = for i in [0..5] do for x in [1..5] do printf "hi"
Run Code Online (Sandbox Code Playgroud)

我期待resultresult2做同样的事情.但结果打印只需一次.result2但是,打印30次.这里缺少什么?

Fyo*_*kin 9

在运算符定义中,exp不一定是函数.您定义运算符的方式exp是任何值.例如,您可以这样做:

[0..1] ->>> 42
Run Code Online (Sandbox Code Playgroud)

这将编译甚至运行,因为运算符定义中没有任何内容需要exp参数作为函数.或其他任何事情.

如果你想exp在循环体内反复进行求值,你需要使它成为一个函数,并确保循环体调用它.既然你对它没有任何要求,那么最简单的就是unit -> 'a.你不必真正声明它的类型,你可以让编译器从它的用途推断它:

let (->>>) lst exp = for i in lst do exp()
Run Code Online (Sandbox Code Playgroud)

注意括号之后exp- 它们表示类型的值unit,从而使表达式exp()成为函数应用程序(即函数exp应用于值()).

当然,有了这个定义,你将无法编写[1..5] ->>> printf "hi",因为printf "hi"它不是一个函数.所以相反,你必须写:

[1..5] ->>> (fun() -> printf "hi")
Run Code Online (Sandbox Code Playgroud)

现在你将打印出5个"hi".

这是因为for .. do语法实际上是语言的一个特殊部分,而不是标准库中定义的"只是另一个函数".使用聪明的函数或运算符定义,您无法真正创建相同的效果.

如果您想要一种构造比函数和运算符更复杂的语法的方法,请查看计算表达式.