English 中文(简体)
F#: Storing and mapping a list of functions
原标题:

I have a number of events that happen in a game. I want to control the time and order at which these events occur.

For example:

Event 1: Show some text on screen for N frames & play a sound effect

Event 2: Clear the text on the screen

My solution (maybe there is a better one), is to have a list of functions that contain the events. The events perform their behavior then return the next events to occur in the game. I thought of using List.map or List.collect because I am essentially mapping a list of events to a new list of events while performing some behavior code.

In the example above, Event1 can be composed of two functions: One that shows text and one that plays a sound (hence the need for a list). The function that shows text would return a copy of itself for N-1 frames then it would return Event2 which clears the text. The play sound function would return the equivalent of a no-op.

If this is a good solution, I could probably do it in C++ or C#. My goal is to do an equivalent or better solution in F#.

最佳回答

Did you mean something like this?

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

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

**Edit: ** if you want to be able to add actions, maybe it s better to make an action dispenser that uses a Queue internally, since appending is O(N) with a list and O(1) with a Queue:

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)
问题回答

Not quite sure what you re trying to achieve here... it can be helpful to think through the exact types that you re looking for. It sounds like perhaps you want to map a (unit->(unit->unit)) list to a (unit->unit) list by applying each function in the first. If that s the case, you can do it like so:

let l = [(fun () -> (fun () -> printfn "first nested fn")); (fun () -> (fun () -> printfn "second nested fn"))]
let l  = List.map (fun f -> f()) l

If you are looking for a syntax to declare your list type then here is one way to do this:

List<`a->`b>

This assumes that the function takes a single parameter.

But the very fact that you are trying to figure out the syntax for the type is a hint that you are still looking at this as if you are coding in procedural language.

The "functional" way of doing it is to concentrate on the logic of generating the list and let the compiler to infer the type based on your code

I ve read your question twice, and am still not sure I understand exactly what you want. But from what I understand, your events aren t necessarily invoked in the order they appear in the list . If this is the case, you don t really want an F# list, you want some kind of lookup.

Now the other question is whether it is really a good idea for an event to determine what should follow it? That kind of amounts to hard coding your functionality once and for all, doesn t it?

EDIT

I see in a comment that you say you want to chain function calls together .

How about writing them one after the other? We aren t in Haskell after all, F# will fire them in the order you write them.

If you want to be a little bit more functional, you could use continuations - each function takes an extra parameter which is the next function to execute. Almost monadic (I believe), except that in your case they appear to be actions, so there are no values to string through from one function to the next.

Not sure if that helps: I think you ll have to try rephrasing your question, judging by the diversity of answers here.

It seems like you are trying to do something in a very complicated way. That is sometimes necessary, but usually it isn t.

Since you are asking this question, I assume that you have more experience in imperative languages. It seems that the real solution to your problem is something completely different than a list of functions.





相关问题
Finding a class within list

I have a class (Node) which has a property of SubNodes which is a List of the Node class I have a list of Nodes (of which each Node may or may not have a list of SubNodes within itself) I need to be ...

How to flatten a List of different types in Scala?

I have 4 elements:List[List[Object]] (Objects are different in each element) that I want to zip so that I can have a List[List[obj1],List[obj2],List[obj3],List[obj4]] I tried to zip them and I ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

Is List<> better than DataSet for UI Layer in ASP.Net?

I want to get data from my data access layer into my business layer, then prepare it for use in my UI. So i wonder: is it better to read my data by DataReader and use it to fill a List<BLClasses&...

What is the benefit to using List<T> over IEnumerable<T>?

or the other way around? I use generic lists all the time. But I hear occasionally about IEnumerables, too, and I honestly have no clue (today) what they are for and why I should use them. So, at ...

灵活性:在滚动之前显示错误的清单

我有一份清单,在你滚动之前没有显示任何物品,然后这些物品就显示。 是否有任何人知道如何解决这一问题? 我尝试了叫人名单。

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签