【问题标题】:F# Mutable Variables inside closures - IDictionary.Item闭包内的 F# 可变变量 - IDictionary.Item
【发布时间】:2013-12-16 10:43:23
【问题描述】:

我正在尝试在 F# 中遍历 IDictionary(原因稍后解释...),并将每个值四舍五入到指定的精度。基本上这就是我想要做的:

List.iter (fun(x) -> a.Item(x) <- Math.Round(a.Item(x), input.precision)) (ICollectionToDoubleList a.Keys)

(其中 ICollectionToDoubleList 采用 ICollection a.Keys 并将其转换为双重列表)。 但是,由于您无法更改闭包内的可变变量,因此无法编译。

我的第一次尝试是这样的:

List.iter (fun(x) ->    let p = Math.Round(a.Item(x), input.precision)
                        a.Item(x) := p
                        ) (ICollectionToDoubleList a.Keys)

但是我得到了错误:

This expression was expected to have type
    'a ref
but here has type
    double

关于a.Item(x)

我可以将 IDictionary 转换为两个列表(或元组列表),执行舍入,然后重新转换为 IDictionary,但这似乎有点混乱和令人费解。

非常感谢任何指导。

编辑:

我忘了说a被定义为:

let mutable (a : IDictionary<double,double>) = ...

【问题讨论】:

  • 只是一个简单的问题,为什么不使用不可变的Map?那么代码会简单得多:)
  • 如果可能的话,我不想创建一个新集合。
  • 嗯...好吧,那是为什么呢?我只是好奇...

标签: f#


【解决方案1】:

我想你想要

a.Item(x) <- p

在 F# 中,您使用 &lt;- 分配给可变值,而 := 分配给 ref 值。

你甚至可以使用

a.[x] <- p

对于一个稍微简单的版本。

解释 mutable 的含义(它的行为与 C 中的 const 相反)

let mutable m = [|1|]
let t = [|1|]
m.[0] <- 0
t.[0] <- 0 //neither of these change m or t - only elements so they are fine
m <- [|1;2;3;|]  //fine as m is mutable
t <- [|1;2;3;|]  //not allowed as t is not mutable

如果你习惯了C中的const,上面的大致相当于

int* m = {1};
const int* t = {1}

注意,两者都不等同于

const int* q const = {1}

这就是我认为你认为不可变的意思。

【讨论】:

  • 这可以在机箱外工作,但我在机箱内使用它。
  • 真的,这是为我编译的 - &gt; let test = System.Collections.Generic.Dictionary&lt;int,int&gt;() List.iter (fun(x) -&gt; test.Item(x) &lt;- 5) ([]);;
  • 我相信这是 FSI 的一个怪癖!当作为源文件编写时,它不会在 VS 2012 中编译。
  • @Nick - 该代码也可以使用编译器为我编译。也许发布您无法编译的完整示例。
  • 你没有把测试写成可变的。它确实可以在不可变的情况下编译,但是我认为 List.iter 实际上不会做任何事情是对的吗?
【解决方案2】:

好的,我找到了答案……

我将 a 定义为:

let mutable (a : IDictionary<double,double>) = ...

如果我把它改成

let (a : IDictionary<double,double>) = ...

然后编译。对我来说,一个不可变的值可以被改变,但一个可变的变量不能,这似乎有点违反直觉!

【讨论】:

  • 对字典的引用是否可变与字典是否允许更改其中的内容无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多