2009-11-22 114 views
3

我有一些事件发生在游戏中。我想控制这些事件发生的时间和顺序。F#:存储和映射功能列表

例如:

事件1:在屏幕上显示N个部分的文字框&播放声音效果

事件2:清除屏幕上的文本

我的解决方案(也许有更好的一个),就是有一个包含事件的函数列表。事件执行他们的行为,然后返回下一个事件发生在游戏中。我想过使用List.map或List.collect,因为我实际上是在执行某些行为代码时将事件列表映射到新的事件列表。

在上面的例子中,Event1可以由两个功能组成:一个显示文本和一个播放声音(因此需要列表)。显示文本的函数会为N-1帧返回自身的副本,然后返回清除文本的Event2。播放声音功能将返回相当于无操作。

如果这是一个很好的解决方案,我可以用C++或C#来做。我的目标是在F#中做一个等效或更好的解决方案。

+0

你想用你的函数列表解决什么问题? – 2009-11-22 21:47:10

+0

我已经改变了原来的问题,因为它在解决方案空间中定义;没有问题的空间。我希望这可以清除事情。 – rysama 2009-11-22 22:36:22

回答

5

你的意思是这样吗?

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#交互):

> 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 =() 
> 

**编辑:**如果你希望能够加入行动,也许是更好地使一个使用队列内部动作饮水机,因为追加是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) 
+0

很好的答案,+1加入一个模棱两可的问题努力! – Benjol 2009-11-23 12:10:38

2

不太清楚你想在这里实现什么......它可以帮助你思考你正在寻找的确切类型。这听起来像也许你想通过在第一个应用每个函数将(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 
+0

我的目标是将函数调用链接在一起。例如,函数“foo”会返回下一个要调用的函数“bar”。 – rysama 2009-11-22 21:21:01

2

如果你正在寻找一个语法来声明您的列表类型,然后在这里是为了做到这一点的一种方法:

List<`a->`b> 

这假定该函数采用单个参数。

但是你试图弄清楚这个类型的语法的一个事实是暗示你仍然在看着这个,就好像你在编程过程语言一样。

做的“功能性”的方式是集中生成列表的逻辑,让编译器来推断根据您的代码的类型

0

好像你正在尝试做的事情非常复杂的方式。这有时是必要的,但通常不是。

既然你问这个问题,我假设你有更多的命令式语言经验。看来您的问题的解决方案与功能列表完全不同。

+0

这不是一个答案它是一个评论 – 2011-04-09 03:08:13

1

我已经读过两遍你的问题,但我仍然不确定自己明白你想要什么。但根据我的理解,您的“事件”不一定按照它们出现在“列表”中的顺序调用。如果是这样的话,你并不是真的想要一个F#列表,你需要某种查找。

现在的另一个问题是,确定一个事件应该遵循的是一个好主意吗?这种相当于一劳永逸的硬编码功能,不是吗?

编辑

我,你说你要“链函数调用一起”评论见。

如何一个接一个地写它们?毕竟,我们不在Haskell中,F#会按照你写的顺序来解雇他们。

如果您希望更具功能性,您可以使用延续 - 每个函数都需要一个额外的参数,这是下一个要执行的函数。几乎一元(我相信),除了你的情况,他们似乎是行动,所以没有值从一个函数串到下一个。

不知道这是否有帮助:我认为你必须尝试改写你的问题,从这里的答案的多样性来判断。