Xbox에서의 개발을 위해 F # 사양의 최종 워크 플로의 수정 된 버전을 사용하고 있습니다. Xbox의 .net 프레임 워크는 꼬리 호출을 지원하지 않습니다. 이 때문에 컴파일 할 때 꼬리 호출 최적화를 비활성화해야합니다.최종 워크 플로우를 사용할 때 꼬리 호출 최적화가 어려움이 있습니까?
처음에는이 제한으로 인해 계산식에서 루핑 형식이 사용되지 않는 것처럼 보일 수도 있지만 처음에는 "스테핑"으로 문제를 피할 수 있다고 생각했습니다. 계산식의 재귀 함수 f가 자체를 호출하지 않습니다. 대신에 f를 호출하는 람다를 포함하는 Eventually 값을 반환합니다.
실험은 while 회 돌이 (계산식에 사용될 때 스택 오버플로가 발생하지 않음)에 대한 것이었지만 재귀 함수에 대해서는 발생하지 않았습니다. 명확히하기 위해
는,이 작품 : 이것은 스택 오버 플로우가 발생
// Wait until "start" or "A" is pressed on one of the gamepads.
// Set "player" when that happens.
let player : PlayerIndex option ref = ref None
while (!player).IsNone do
for p in all_players do
let state = GamePad.GetState(p)
if state.IsConnected
&& (state.Buttons.Start = ButtonState.Pressed
|| state.Buttons.A = ButtonState.Pressed) then
player := Some p
do! sys.WaitNextFrame()
: 두 번째 경우
// Wait until "start" is pressed on the controlling gamepad.
let rec wait() = task {
input.Update()
if not (input.IsStartPressed()) then
do! sys.WaitNextFrame()
do! wait()
}
을, 스택 추적 통화의 긴 순서를 보여줍니다에 "바인드 @ 17- 1 "이며, 그 코드는 아래와 같습니다. 스택 추적에 나타나는 줄 번호는 줄 17입니다.
let rec bind k e =
match e with
| Completed r ->
Running(fun() -> k r)
| Running f ->
Running(fun() -> f() |> bind k) // line 17
| Blocked(dt, f) ->
Blocked(dt, fun() -> f() |> bind k)
| BlockedNextFrame f ->
BlockedNextFrame(fun() -> f() |> bind k)
| Yield f ->
Yield(fun() -> f() |> bind k)
어디에서 잘못 되었나요? "steppable recursion"에 대한 나의 추론은 무해한가? 스택 오버플로가 잘못 되었습니까? 바인드 구현에 문제가 있습니까?
오 마이 머리! 재귀와 지속적인 통과는 내게 두통을 준다 ...
EDIT : "무거운 w.r.t. 스택 오버플로 가파른 반복"이름을 가지고있다, 나는 방금 배웠다. 그것은 트램펄린이라고합니다.
감사합니다. 작동 중입니다. 지금 내가 왜 그 이유 만 이해한다면 ... '할! 내 코드에서 wait()'암시 적으로'return()'이 뒤따라 왔습니까? – Joh