[英]F#: Storing and mapping a list of functions
我在游戏中发生了很多事件。 我想控制这些事件发生的时间和顺序。
例如:
事件1:在屏幕上显示N帧的一些文本并播放声音效果
事件2:清除屏幕上的文本
我的解决方案(可能有一个更好的解决方案)是拥有包含事件的函数列表。 事件执行其行为然后返回在游戏中发生的下一个事件。 我想过使用List.map或List.collect,因为我实际上是在执行某些行为代码时将事件列表映射到新的事件列表。
在上面的示例中,Event1可以由两个函数组成:一个显示文本,另一个播放声音(因此需要列表)。 显示文本的函数将为N-1帧返回自身的副本,然后它将返回清除文本的Event2。 播放声音功能将返回相当于无操作的声音。
如果这是一个很好的解决方案,我可以用C ++或C#来做。 我的目标是在F#中做同等或更好的解决方案。
你的意思是这样的吗?
let myActions =
[fun () -> printfn "You've woken up a dragon."
fun () -> printfn "You hit the dragon for 0 points of damage."
fun () -> printfn "The dragon belches."
fun () -> printfn "You have died."]
let actionBuilder actionList =
let actions = ref actionList
fun () ->
match !actions with
| [] -> ()
| h::t -> h(); actions := t
用法(F#interactive):
> let doSomething = actionBuilder myActions;;
val doSomething : (unit -> unit)
> doSomething();;
You've woken up a dragon.
val it : unit = ()
> doSomething();;
You hit the dragon for 0 points of damage.
val it : unit = ()
> doSomething();;
The dragon belches.
val it : unit = ()
> doSomething();;
You have died.
val it : unit = ()
> doSomething();;
val it : unit = ()
>
**编辑:**如果你想能够添加动作,也许最好制作一个内部使用Queue的动作分配器,因为追加的是带有列表的O(N)和带有队列的O(1):
type actionGenerator(myActions: (unit->unit) list) =
let Q = new System.Collections.Generic.Queue<_>(Seq.ofList myActions)
member g.NextAction =
fun () ->
if Q.Count = 0 then ()
else Q.Dequeue()()
member g.AddAction(action) = Q.Enqueue(action)
不太确定你在这里想要实现的目标......思考你正在寻找的确切类型会很有帮助。 听起来好像你想通过应用第一个中的每个函数将(unit->(unit->unit)) list
映射到(unit->(unit->unit)) list
(unit->unit) list
。 如果是这样的话,你可以这样做:
let l = [(fun () -> (fun () -> printfn "first nested fn")); (fun () -> (fun () -> printfn "second nested fn"))]
let l' = List.map (fun f -> f()) l
如果您正在寻找声明列表类型的语法,那么这是一种方法:
List<`a->`b>
这假定该函数采用单个参数。
但是你正试图找出该类型的语法这一事实暗示你仍然在看这个就好像你是用过程语言编写的。
这种“功能”的方式是专注于生成列表的逻辑,让编译器根据您的代码推断出类型
我已经两次阅读你的问题了,我仍然不确定我到底知道你想要什么。 但根据我的理解,您的“事件”不一定按照它们出现在“列表”中的顺序调用。 如果是这种情况,你真的不想要一个F#列表,你想要某种查找。
现在另一个问题是,一个事件确定应该遵循什么才是真的好主意? 这类似于一劳永逸地对您的功能进行硬编码,不是吗?
编辑
我在评论中看到你说你想“将函数调用连在一起”。
一个接一个地写它们怎么样? 毕竟我们不在Haskell中,F#会按照你编写它们的顺序触发它们。
如果你想要更具功能性,你可以使用continuation - 每个函数都需要一个额外的参数,这是下一个要执行的函数。 几乎是monadic(我相信),除了在你的情况下它们似乎是动作,所以没有值从一个函数到下一个函数串通。
不确定这是否有帮助:我认为你必须尝试改写你的问题,从这里答案的多样性来判断。
看起来你正试图以一种非常复杂的方式做某事。 这有时是必要的,但通常不是。
既然你问这个问题,我认为你有更多的命令式语言经验。 似乎问题的真正解决方案与功能列表完全不同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.