加载时的 F# 模块效果
F# module effects upon loading
我怀疑这种行为可能不是 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 )
底线是这样的:不受控制的影响是不好的。它们使您的程序不可预测。尽量避开它们。
我怀疑这种行为可能不是 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 )
底线是这样的:不受控制的影响是不好的。它们使您的程序不可预测。尽量避开它们。