处理邮箱处理器内的迭代,Seq.map与Seq.iter

时间:2014-06-12 12:12:50

标签: f# mailboxprocessor

今天我遇到了在MailboxProcessor的迭代中实现一些简单处理的问题。

起初我尝试使用Seq.map进行迭代,但迭代中的代码从未被调用过!然后我转而使用Seq.iter进行迭代,然后处理就完成了......

type Agent<'Msg> = MailboxProcessor<'Msg>

...

let agent = 
    Agent.Start((fun agent -> 
                let rec loop = 
                    async { 
                        let! msg = agent.Receive()
                            match msg with
                            | SensorEvent(id, ts) -> 

                                ...

                                [for x in connections.[id] -> x]
                                |> Seq.map (fun light_id -> //Seq.iter works just fine here, Seq.map doesn't!
                                    let publish = new Publish<SimulatorBroker.SimLightOffMsg>()
                                    publish.Message <- new SimulatorBroker.SimLightOffMsg(light_id, recom_ts)
                                    peer.Publish(box publish :?> IPublish<_>)
                                )
                                |> ignore
                                return! loop
                        }
                    loop), tokenSource.Token)

我感到困惑的是为什么我不能使用Seq.map?...现在我想知道它是否在没有被分配给任何东西时被优化掉了? 或者如果在Mailboxprocessor中使用Seq.map会发生其他奇怪的事情..?

是的,我知道Seq.iter更适合简单的迭代,只返回&#39; unit&#39;无论如何。但请原谅我,我还在学习;)。

2 个答案:

答案 0 :(得分:4)

Seq.map很懒。在您询问序列的元素之前,不会对其进行评估。您可以在地图后执行Seq.toList,它会强行执行。 Seq.iter是严格的,它贯穿序列的所有元素。

尝试使用FSI

Seq.initInfinite id |> Seq.map (fun x -> printfn "%A" x; x)

Seq.initInfinite id |> Seq.iter (fun x -> printfn "%A" x)

因此,在您的情况下,如果您想强制执行并忽略结果,Seq.iter更合适。

答案 1 :(得分:1)

Seq.map操作返回一个新序列,其中包含将指定函数应用于输入序列元素的结果。这意味着您只应在需要对结果执行某些操作时使用它。之所以没有做任何事情&#34;是懒惰地评估序列。这意味着使用Seq.map,您的代码只会构建一个序列,并且不会对其执行任何操作。 (你必须使用ignore明确忽略结果的事实也表明存在错误)。

编写您正在执行的操作的最简单方法是使用命令式for循环结构(与Seq.iter的结构相同):

 for light_id in connections.[id] do
   let publish = new Publish<SimulatorBroker.SimLightOffMsg>()
   publish.Message <- new SimulatorBroker.SimLightOffMsg(light_id, recom_ts)
   peer.Publish(box publish :?> IPublish<_>)