2009-11-22 2 views
3

게임에서 발생하는 여러 가지 이벤트가 있습니다. 나는이 사건들이 일어나는 시간과 순서를 통제하고 싶다.F # : 함수 목록 저장 및 매핑

이벤트 1 : 예를 들어

지우기 화면에 텍스트가 (아마도

내 솔루션이

: N에 대한 화면에 텍스트를보기는 &가

이벤트 2는 사운드 효과를 재생 프레임 더 나은 것)은 이벤트를 포함하는 함수 목록을 갖는 것입니다. 이벤트는 행동을 수행 한 다음 게임에서 다음 이벤트를 반환합니다. 필자는 본질적으로 일부 동작 코드를 수행하는 동안 이벤트 목록을 이벤트의 새 목록에 매핑하기 때문에 List.map 또는 List.collect를 사용하려고 생각했습니다.

위 예제에서 Event1은 텍스트를 표시하는 함수와 사운드를 재생하는 함수 (따라서 목록이 필요함)의 두 가지 함수로 구성 될 수 있습니다. 텍스트를 표시하는 함수는 N-1 프레임에 대해 자체 복사본을 반환하고 텍스트를 지우는 Event2를 반환합니다. play 사운드 함수는 no-op와 같은 것을 반환합니다.

이것이 좋은 해결책이라면 C++이나 C#으로 할 수 있습니다. 내 목표는 F #에서 동급 이상의 더 나은 솔루션을 만드는 것입니다.

+0

기능 목록으로 해결하려는 문제점은 무엇입니까? –

+0

원래 질문을 솔루션 영역에 정의 된대로 변경했습니다. 문제 공간이 아닙니다. 이 일이 깨끗해지기를 바랍니다. – rysama

답변

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

2

여기에서 달성하고자하는 것이 확실하지 않습니다. 찾고있는 정확한 유형을 생각하는 것이 도움이 될 수 있습니다. 첫 번째 함수를 적용하여 을 (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

2

여기에 다음 목록 유형을 선언하는 구문을 찾는 경우입니다이 할 수있는 한 가지 방법 :

List<`a->`b> 

이 있다고 가정을 이 함수는 단일 매개 변수를 사용합니다.

그러나 형식에 대한 구문을 파악하려고한다는 사실은 절차 언어로 코딩하는 것처럼 여전히보고있는 힌트입니다. 당신은 매우에서 뭔가를하려고하는 것처럼

이 목록을 생성의 논리에 집중하고 코드를 기반으로 유형을 추론 할 수있는 컴파일러를하도록하는 것입니다 수행의 "기능"방법은

0

보인다 복잡한 방식. 때로는 필요하지만 일반적으로 그렇지 않습니다.

이 질문을하기 때문에 명령형 언어로 더 많은 경험을했다고 가정합니다. 실제 해결책은 기능 목록과 완전히 다른 것입니다.

+0

이 답변에 대한 답변이 아닙니다 –

1

질문을 두 번 읽었으며 원하는 내용을 정확히 이해하지 못했습니다. 그러나 내가 이해하는 바에 따르면, '이벤트'는 반드시 '목록'에 나타나는 순서대로 호출되는 것은 아닙니다. 이 경우 F # 목록이 실제로 필요하지 않습니다. 어떤 종류의 조회가 필요합니다.

이제 다른 문제는 이벤트가 이벤트를 따라야한다는 것을 결정하는 것이 실제로 좋은 아이디어인지 여부입니다. 이런 종류의 기능은 한 번에 모든 기능을 하드 코딩 할 수 있습니다. 그렇지 않습니까?

편집 나는 당신이 당신에게 '체인 기능을 함께 호출'싶은 말은 코멘트에서 볼

.

어떻게 하나씩 작성하나요? 결국 우리는 하스켈에 있지 않습니다. F #는 당신이 쓰는 순서대로 그들을 해고 할 것입니다.

좀 더 기능적으로 사용하려면 연속을 사용할 수 있습니다. 각 함수는 실행할 다음 함수 인 추가 매개 변수를 사용합니다. 귀하의 경우에는 행동으로 보이는 것을 제외하고는 거의 모나드 식 (나는 믿습니다), 한 기능에서 다음 기능으로 문자열을 전달할 가치가 없습니다.

도움이되는지 확실하지 않은 경우 : 여기에 답변의 다양성으로 판단하여 질문을 수정해야합니다.