簡體   English   中英

F#:存儲和映射函數列表

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM