Używam zmodyfikowanej wersji Ostatecznie workflow ze specyfikacji F # do mojego rozwoju na Xboksie. Wydaje się, że platforma .net na Xboksie nie obsługuje połączeń wychodzących. Z tego powodu podczas kompilacji muszę wyłączyć optymalizację połączeń końcowych.Czy brak optymalizacji wywołań końcowych jest przeszkodą podczas korzystania z przepływu pracy W końcu?
Chociaż może się wydawać, że to ograniczenie uniemożliwi użycie jakiejkolwiek formy pętli w wyrażeniach obliczeniowych, początkowo myślałem, że "krokowanie" pozwoli uniknąć tego problemu: funkcja rekurencyjna f w wyrażeniu obliczeniowym nie nazywa się sama bezpośrednio, zamiast tego zwraca wartość końcową zawierającą lambdę, która wywołuje f.
Eksperymenty wskazują, że miałem rację co do pętli (nie powodują one przepełnień stosu w wyrażeniach obliczeniowych), ale nie dotyczą funkcji rekursywnych.
Aby wyjaśnić to działa:
// 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()
To powoduje przepełnienie stosu:
// 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()
}
W drugim przypadku, ślad stosu przedstawia długą sekwencję wywołań „wiążą @ 17- 1 ", którego kod przedstawiono poniżej. Numer wiersza pojawiający się w zapisie stosu to linia 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)
Gdzie się mylę? Czy moje rozumowanie o "steppable recursion" jest nieszkodliwe w.r.t. przepełnienie stosu jest nieprawidłowe? Czy coś jest nie tak z moją implementacją bind?
O, moja głowa! Kontynuacja - przekazywanie z rekursją daje mi bóle głowy ...
EDYCJA: "rekurencja krokowa jest nieszkodliwym przepełnieniem stosów w.r.t" ma nazwę, właśnie się nauczyłem. Nazywa się to trampoliną.
Dzięki, to działa! Teraz, jeśli tylko zrozumiałem, dlaczego ... Czy to ma coś wspólnego z faktem, że 'zrobić! wait() 'w moim kodzie został niejawnie poprzedzony przez' return() '? – Joh