F# MailboxProcessor内的迭代处理,Seq.map与Seq.iter

F# MailboxProcessor内的迭代处理,Seq.map与Seq.iter,f#,mailboxprocessor,F#,Mailboxprocessor,今天,我在MailboxProcessor的迭代中实现一些简单的处理时遇到了一个问题 起初,我尝试使用Seq.map进行迭代,但从未调用过迭代中的代码!然后我转而使用Seq.iter进行迭代,然后处理就完成得很好了 type Agent<'Msg> = MailboxProcessor<'Msg> ... let agent = Agent.Start((fun agent -> let rec loop =

今天,我在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)
类型代理
...
让代理=
代理。开始((有趣的代理->
让rec循环=
异步{
让!msg=agent.Receive()
配味精
|传感器事件(id,ts)->
...
[用于x in连接。[id]->x]
|>Seq.map(fun light_id->//Seq.iter在这里工作得很好,Seq.map不行!
让发布=新发布()
publish.Message(我发布)
)
|>忽略
返回!循环
}
循环),tokenSource.Token)
我感到困惑的是为什么我不能使用Seq.map?。。现在我想知道,当它没有分配给任何东西时,它是否会得到优化?。。 或者,如果在Mailboxprocessor中使用Seq.map时发生了其他奇怪的情况?


是的,我知道Seq.iter更适合只返回“unit”的简单迭代。但请原谅我,我还在学习

Seq.map
是惰性的。在您询问序列的元素之前,不会对其进行计算。您可以在映射之后执行
Seq.toList
,它将强制执行该操作。 iter是严格的,它贯穿于序列的所有元素

试一试FSI

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


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

Seq.map
是惰性的。在您询问序列的元素之前,不会对其进行计算。您可以在映射之后执行
Seq.toList
,它将强制执行该操作。 iter是严格的,它贯穿于序列的所有元素

试一试FSI

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


因此,在您的情况下,如果您想要强制执行并忽略结果,
Seq.iter
更合适。
Seq.map
操作返回一个新序列,其中包含将指定函数应用于输入序列元素的结果。这意味着您应该只在需要对结果进行处理时使用它。它“什么都不做”的原因是序列的评估是懒惰的。这意味着使用
Seq.map
,您的代码只构建一个序列,而不做任何处理。(您必须使用
ignore
显式忽略结果这一事实也表明存在问题)

编写所做操作的最简单方法是使用命令式
进行循环构造(这与
Seq.iter
所做的相同):

用于连接中的灯光标识。[id]do
让发布=新发布()
publish.Message(我发布)

Seq.map
操作返回一个新序列,其中包含将指定函数应用于输入序列元素的结果。这意味着您应该只在需要对结果进行处理时使用它。它“什么都不做”的原因是序列的评估是懒惰的。这意味着使用
Seq.map
,您的代码只构建一个序列,而不做任何处理。(您必须使用
ignore
显式忽略结果这一事实也表明存在问题)

编写所做操作的最简单方法是使用命令式
进行循环构造(这与
Seq.iter
所做的相同):

用于连接中的灯光标识。[id]do
让发布=新发布()
publish.Message(我发布)

这是有意义的,因为
Seq.map
是为输入和输出而设计的;为什么要在需要结果之前就产生结果,特别是如果你从来没有这样做过的话?然而,
Seq.iter
采用了一个方法返回单元,所以这都是关于副作用的。这是有意义的,因为
Seq.map
是为输入和输出而设计的;为什么要在需要结果之前就产生结果,特别是如果你从来没有这样做过的话?而
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<_>)