2

我完全不知道为什么这段代码不会改变一系列类型的成员变量:

for p in prescrs do
    p.ATC <- "A"
    for c in p.Drug.Components do
        for s in c.Substances do
                s.DoseTotal.Adjust <- adjustKg
                s.DoseTotal.Time <- "DAY"
                s.DoseTotal.Unit <- s.DrugConcentration.Unit
                s.DoseRate.Adjust <- adjustKg
                s.DoseRate.Time <- "DAY"
                s.DoseRate.Unit <- s.DrugConcentration.Unit

prescrs 是一系列 Prescriptions,它是一个非常简单的“POCO”,定义为具有成员值的类型。我不知道为什么这不起作用。

我尝试了一个简单的测试用例,例如:

type IterTest () =
    member val Name = "" with get, set
    member val IterTests = [] |> List.toSeq : IterTest seq with get, set

let iterseq = 
    [
        new IterTest(Name = "Test1")
        new IterTest(Name = "Test2")
    ] 
    |> List.toSeq

iterseq |> Seq.iter(fun x -> x.IterTests <- iterseq)
iterseq |> Seq.iter(fun x -> 
    x.IterTests
    |> Seq.iter(fun x' -> x'.Name <- "itered"))

但是这里的结果与预期的一样。所以,甚至不能完全重现我的问题???

找到了解决方案(没有真正理解上面的问题)。当我第一次将 prescrs 序列转换为如下列表时:

let prescrs = prescrs |> Seq.toList

然后执行命令式循环,属性确实会发生变化。

4

1 回答 1

4

试试这个示例:

type Mutable() = 
    member val Iterated = false with get, set

let muts = Seq.init 5 (fun _ -> printfn "init"; Mutable())

let muts2 = muts // try again with let muts2 = muts |> List.ofSeq

printfn "Before iter"

for a in muts2 do
    printfn "iter"    
    a.Iterated <- true 

printfn "After iter" 

muts2 |> List.ofSeq

iter并检查如何init交错。

Seqs是惰性的,但一旦计算就不会被缓存。因此,即使您强制尝试改变prescrs序列中的某些元素,一旦您再次拉动,一切都会消失prescrs。如果您prescrs在进行突变之前更改为具体的集合类型(如列表),您将不再遇到同样的问题。请注意,如果您拥有的是 seq 内的 seq 内的 seq,事情可能会变得更加棘手。

最好的想法是首先避免突变。

于 2014-12-02T01:14:24.983 回答