我有一些计算。
在这个例子中,一个非常简单的循环是for
循环。实际上,在测试之后,我将有一个循环来处理实时流数据。
open System.Collections.Generic
let updates = new List<int>()
let appendToAList number =
updates.Add number
printfn "Added: %i" number
let test =
for num in [1..100] do
appendToAList num
num * 2 |> ignore
我的目标是实现appendToAList
,这个函数可以获取有关正在进行的计算的一些额外信息(跟踪其执行所需的信息),并将结果堆叠在合适的数据结构中。是否有可变列表的功能替代?
谢谢。
编辑:有关achitecture的更多信息
不确定这会有所帮助,但是 - 长话短说 - 我正在建立一个交易系统。
我的代码中的一些片段:
// defines the action steps when new data is received
let processFeed (date, feed:Matrix) = stateMonad<Matrix, Matrix> {
do! strategy.ApplyPnL feed
do! strategy.RecalibrateFilter feed
let! signal' = strategy.Signal feed
do! strategy.Trade feed signal' }
此部分采用时间戳和新鲜市场报价。 Strategy
包含了一些数学函数。根据客户需求,该策略可以重新校准,提取信号并最终拍摄订单。为了使事情更精简,状态monad带有算法和投资组合的状态(金钱,股票等)。
目前,我必须运行模拟(回测)以评估事情是否正常。基本上,我遍历历史数据。
// process the historical data
let rows = seq { for idx = 0 to 3 do yield (dataframe.GetRowKeyAt(idx), data.[[idx], [0..3]]) } // for debugging purposes here I have replaced data.Size.[0]-1 with 3
let simulation = stateMonad<Matrix, Matrix> {
for row in rows do
do! processFeed row }
在for
循环中运行的完全相同的代码将来应该在一个看起来像
...
let runLive =
while (isConnected)
let newFeed = GetSomehowDataFromTheMarket
do! processFeed newFeed
我还没有解决这个问题,我正在学习F#,请原谅这个无意义的伪代码。
我需要的是一种巧妙的方法,可以从循环中获取信息并对其进行处理(以gui显示,绘制一些数据等)。换句话说,我需要草拟算法将如何向用户报告。
我已经开始尝试将算法的状态堆叠在一个列表中,这样我最终可以开始绘制一些东西。
如果我可以运行在单独的线程上处理报告的函数,那将是很好的,所以我有兴趣学习一种功能性的方法来完成所有这些,这有助于设计易于并行化的东西。
答案 0 :(得分:1)
最好删除你的循环并做这样的事情(除非你的其他要求阻止它):
let test = [1..100] |> List.fold (fun state number-> printfn "Added: %i" number
number::state) []
F#标准列表(与List
中的System.Collections.Generic
类型不同)是不可变的。另外,请注意不再有任何可变变量。如果您不熟悉F#列表类型,[]
会创建一个空列表,并在项目和列表之间放置::
会创建一个包含该项目的新列表。
答案 1 :(得分:1)
即使你有一些全局状态(例如某些实时流产生的值),使用 immutable 功能列表也可能有意义,但有一个可变引用。
这个想法是,你可以非常便宜地附加元素(在前面),并且在任何时候,你都可以安全地获得对当前列表的引用(并且同时处理它,同时构造新状态 - 没有影响处理列表早期快照的进程。)
所以你可以使用类似的东西:
let mutable updates = []
let appendToAList number =
updates <- number::updates
printfn "Added: %i" number
let test =
for num in [1..100] do
appendToAList num
num * 2 |> ignore
最佳选择实际上取决于您考虑的实际情况 - 因此,如果您想获得更好的答案,请尝试描述您正在设计的系统/架构。
答案 2 :(得分:1)
如果我正在处理实时数据流的处理,我可能会使用某种事件流解决方案,其中每个计算的结果触发一个事件。
根据计算结果(可能存在错误或特定范围内的值的特殊情况等),您可以使用Observable
模块构建具有特定规则等的事件管道。您的管道可以通过将结果和时间信息存储在数据库中,或者绘制到UI或其他内容来结束。
这样你就可以完全取消你的可变状态。
let event = new Event<int>()
let observable = event.Publish
// Example rules: Even numbers are successes and odd numbers are errors
let evens, odds = observable |> Observable.partition (fun i -> i%2=0)
evens |> Observable.subscribe (printfn "Success: %i")
odds |> Observable.subscribe (printfn "Error: %i")
let appendToList number =
event.Trigger(number)
let test =
for num in [1..100] do
appendToList num
num * 2 |> ignore
这可能完全不合适,也许您需要适合某种设计才能插入现有系统或其他任何系统。但话说回来,它也可能有所帮助! - 希望是后者。