syntax - F#:为什么我必须为不带参数的函数显式指定 'unit'?

标签 syntax f# function

所以我刚刚完成了我的第一个 F# 程序,我唯一的功能背景是一点点 Haskell 知识(阅读:还没有真正在其中生成任何程序)。

在经历了一些令人难以置信的行为之后,我开始意识到 F# 区分了:

prepareDeck = allSuits |> List.collect generateCards |> shuffle


prepareDeck() = allSuits |> List.collect generateCards |> shuffle

我注意到它“缓存”了前者,如果再次调用它就不会重新计算它,而它将后者视为普通函数。如果有问题的函数没有副作用,你无法区分,显然,但我的 shuffle做过!

这应该是常识吗?我还没有看到任何教程 Material 中提到它。原因只是解析器的一个弱点,有点像你在使用之前声明一个函数?

最佳答案

大多数 F# Material 确实解释了模块中的所有顶级语句都是在声明时自上而下执行的。换句话说,您声明的不是函数,而是在程序运行时绑定(bind)一次的值。

查看反射(reflect)的代码确实很有帮助。我有一个简单的文件:

let juliet = "awesome"
let juliet2() = "awesome"

编译后的代码如下所示:
public static string juliet
{
    [CompilerGenerated, DebuggerNonUserCode]
    get
    {
        return "awesome";
    }
}

//...

public static string juliet2()
{
    return "awesome";
}

所以一个是静态属性,另一个是函数。这是一个理想的属性,因为想象一下如果我们有这样的东西:
let x = someLongRunningDatabaseCall()

我们只想要 x绑定(bind)一次,我们不希望它每次访问时都调用数据库函数x .

此外,我们可以编写如下有趣的代码:
> let isInNebraska =
    printfn "Creating cities set"
    let cities = set ["Omaha"; "Bellevue"; "Lincoln"; "Papillion"; "La Vista"; "Ralston"]
    fun n -> cities.Contains(n);;
Creating cities set

val isInNebraska : (string -> bool)

> isInNebraska "Omaha";;
val it : bool = true

> isInNebraska "Okaloosa";;
val it : bool = false

由于isInNebraska是一个值,它立即被评估。它的数据类型恰好是 (string -> bool) , 所以它看起来像一个函数。结果,我们只填写了cities即使我们调用该函数 1000 次,也设置一次。

让我们将该代码与此进行比较:
> let isInNebraska2 n =
    printfn "Creating cities set"
    let cities = set ["Omaha"; "Bellevue"; "Lincoln"; "Papillion"; "La Vista"; "Ralston"]
    cities.Contains(n);;

val isInNebraska2 : string -> bool

> isInNebraska2 "Omaha";;
Creating cities set
val it : bool = true

> isInNebraska2 "Okaloosa";;
Creating cities set
val it : bool = false

糟糕,每次调用该函数时,我们都会创建一个新的城市集。

因此,值(value)和功能之间肯定存在合法和真实的区别。

关于syntax - F#:为什么我必须为不带参数的函数显式指定 'unit'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2166280/

相关文章:

c# - 这个用于构造基本 Windows.Form 的简单 F# 代码的 C# 版本是什么?

javascript - 未调用的 javascript 函数在其他函数执行期间启动

c++ - c++ 函数签名附加关键字是什么?

c++ - *(int*)&data[18] 在此代码中实际做了什么?

python - 在 Python 中检查多个变量等于单个值的更好方法

Scala - 将函数传递给 Future.apply

haskell - 在无限序列生成期间删除元素

.net - 将数据从 Matlab 应用程序服务器传输到 F#

function - Swift 类函数

syntax - 在Raku类定义中, "has"关键字在 "method"之前是什么意思?