为什么 Item set 没有按预期工作?

Why does Item set not work as expected?

type dMatrix with
    member t.Item
        with get(a: int, b: int) = t.dArray.[b+a*t.num_cols |> SizeT]
        and set(a: int, b: int) (value: floatType) = t.dArray.[b+a*t.num_cols |> SizeT] <- value
    member t.setItem(a: int, b: int) (value: floatType) = t.dArray.[b+a*t.num_cols |> SizeT] <- value

let a = dMatrix.createRandomUniformMatrix n m 50.f 50.0f

a.[1,1] <- 654.0f // Gives 'A value must be mutable in order to mutate the contents or take the address of a value type, e.g. 'let mutable x = ...''
a.setItem(1,1) 654.0f // Works fine.

我不确定上面发生了什么。如果有帮助,dArrayManagedCuda 库中的 CudaDeviceVariable<float32> 类型。

编辑:

type dMatrix = 
    struct
        val num_rows:int
        val num_cols:int
        val dArray: CudaDeviceVariable<floatType>

上面的结构是这样的。即使我使 dArray 可变,它仍然不起作用,但是写 a.dArray.[SizeT 0] <- 2.5f 之类的东西就可以了。有什么解决方法吗?

Edit2: 把上面的变成一个记录或者一个class解决问题。

错误消息在这里很有帮助。在 F# 中,默认情况下值是不可变的。必须明确声明可变性,请参阅:https://msdn.microsoft.com/en-us/library/dd233185.aspx

如果你想让 a 可变,请执行:

let mutable a = dMatrix.createRandomUniformMatrix n m 50.f 50.0f

通常不需要做一些事情 mutable 除非你想改变值本身(而不是改变该对象的成员之一),这种行为在值和引用类型之间是不同的,因为实例这将编译:

let a = [|5; 10; 9; 3; 2|]
a.[2] <- 6

但是如果 a 是带有索引器的 a 结构,它就不会。例如,此结构产生与您描述的完全相同的行为:

type TestStruct =
    struct 
        val mutable Xs : int[]
    end

    member this.Item
        with get(i) = this.Xs.[i]
        and set(i : int) (value) = this.Xs.[i] <- value

    member this.SetValue i y =
        this.Xs.[i] <- y

所以,我猜你涉及到值类型。