试图按顺序改变财产完全失败了

时间:2014-12-02 00:05:08

标签: f# seq imperative

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

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&#39;定义为具有成员值的类型。我不知道为什么这不起作用。

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

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

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

1 个答案:

答案 0 :(得分: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

并检查iterinit是如何交错的。

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

最好的办法是尽量避免突变。