封闭内的F#Mutable变量 - IDictionary.Item

时间:2013-12-16 10:43:24

标签: f#

我试图在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

on a.Item(x)

我可以将IDictionary转换为两个列表(或元组列表),执行舍入,并重新转换为IDictionary,但这看起来有点混乱和错综复杂。

非常感谢任何指导。

编辑:

我忘了提到a被定义为:

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

2 个答案:

答案 0 :(得分:2)

我想你想要

a.Item(x) <- p

在F#中,您使用<-分配可变值,同时:=分配给ref值。

你甚至可以使用

a.[x] <- p

稍微简单的版本。

解释什么是可变的意思(它的行为与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}

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

答案 1 :(得分:0)

好的,所以我发现了答案......

我已将a定义为:

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

如果我将其更改为

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

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