gpt4 book ai didi

module - F# 模块加载时的效果

转载 作者:行者123 更新时间:2023-12-02 03:57:30 25 4
gpt4 key购买 nike

我怀疑这种行为可能并非 F# 所独有,但我会选择它,因为我在工作中使用的是它。

假设我有一个模块

open System

module Bar =
let bar =
Console.WriteLine("BAR!")
"bar"

我在 fsx 中有以下内容:

// this is a standard library function (Operators.defaultArg or Option.defaultValue)
let getValueOr v = function
| Some x -> x
| None -> v

let opt = Some "foo"

Console.WriteLine( opt |> getValueOr Bar.bar )

当我运行它时,我看到以下打印内容

BAR!
foo

这是预期的,因为参数通常在函数体之前评估,所以我希望 Bar.bar 中的效果在 getValueOr 部分应用它之前发生(甚至当模块被读取时)。

但是,当我将 Bar 模块编译成 DLL 并#r 时,我看到的只是

foo

换句话说,Bar.bar 不会被评估...为什么?是因为#r吗?

对于我想要创建的东西来说,这种行为实际上是理想的,但它有点违反直觉,我想更好地理解它。

最佳答案

这是由于优化而发生的。

当您在 FSI 中运行时,优化会关闭,因此一切都会按照您期望的方式运行。

但是当您在 Release 中进行编译时(即通过优化),F# 编译器能够执行更多操作,因为它知道代码的结构。在这种情况下,函数 getValueOr 在调用站点内联,最后一行大致如下:

// C# syntax
Console.WriteLine( foo == null ? Bar.bar : foo.Value )

这是另一个有趣的实验:如果将 Bar 模块的定义移动到引用 Bar.bar 的同一位置,效果将(可能)重新出现,因为 bar 本身的定义将被内联,大致如下:

// C# syntax:
Console.WriteLine( "BAR!" )
var bar = "bar"
var foo = new Some("foo")
Console.WriteLine( foo == null ? bar : foo.Value )
<小时/>

底线是这样的:不受控制的影响是不好的。它们使您的程序变得不可预测。尽量避开它们。

关于module - F# 模块加载时的效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51792433/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com