1

I'm developing a poker app i almost have it done and im looking for improvements and 1 of the things i wonder about is should i change my main looping method method ? Currently it's looping by using tail recursive call. However friend of mine suggested me to switch it to a iteration since it's using a while loop and loop's don't require stack space. Here's my code as it is now.

private async Task Turns()
    {
        _turns = ReturnTurns();
        GC.KeepAlive(Updates);
        if (!Player.FoldTurn && Player.Chips > 0)
        {
            if (Player.Turn)
            {
                SetPlayerStuff(true);
                Call -= Player.PreviousCall;
                _up = int.MaxValue;
                _turnCount++;
                Bot1.Turn = true;
                _restart = true;
            }
        }
        if (!Player.Turn)
        {
            await Flip(0);
        }
        if (Player.FoldTurn || !Player.Turn || Player.Chips <= 0)
        {
            Call = TempCall;
            if (StatusLabels[Player.EnumCasted].Contains(RepetitiveVariables.Fold))
            {
                Bot1.Turn = true;
            }
            SetPlayerStuff(false);
            Bot1 = (Bot)await RotateTurns(Bot1, Bot1.EnumCasted);
            Bot2 = (Bot)await RotateTurns(Bot2, Bot2.EnumCasted);
            Bot3 = (Bot)await RotateTurns(Bot3, Bot3.EnumCasted);
            Bot4 = (Bot)await RotateTurns(Bot4, Bot4.EnumCasted);
            Bot5 = (Bot)await RotateTurns(Bot5, Bot5.EnumCasted);
            _restart = false;
        }
        if (!_restart)
        {
            await Turns();
        }
    }

That's how i think it should look's like with a loop:

    private async Task Turns()
    {
        while (true)
        {
            _turns = ReturnTurns();
            GC.KeepAlive(Updates);
            if (!Player.FoldTurn && Player.Chips > 0)
            {
                if (Player.Turn)
                {
                    SetPlayerStuff(true);
                    Call -= Player.PreviousCall;
                    _up = int.MaxValue;
                    _turnCount++;
                    Bot1.Turn = true;
                    _restart = true;
                }
            }
            if (!Player.Turn)
            {
                await Flip(0);
            }
            if (Player.FoldTurn || !Player.Turn || Player.Chips <= 0)
            {
                Call = TempCall;
                if (StatusLabels[Player.EnumCasted].Contains(RepetitiveVariables.Fold))
                {
                    Bot1.Turn = true;
                }
                SetPlayerStuff(false);
                Bot1 = (Bot) await RotateTurns(Bot1, Bot1.EnumCasted);
                Bot2 = (Bot) await RotateTurns(Bot2, Bot2.EnumCasted);
                Bot3 = (Bot) await RotateTurns(Bot3, Bot3.EnumCasted);
                Bot4 = (Bot) await RotateTurns(Bot4, Bot4.EnumCasted);
                Bot5 = (Bot) await RotateTurns(Bot5, Bot5.EnumCasted);
                _restart = false;
            }
            if (!_restart)
            {
                continue;
            }
            break;
        }
    }
3
  • 3
    Find 10 differences questions should be asked at code review I think. If you have concerns, then you have to provide us with details, not "take my code, test it, make it better and answer" way. Commented Feb 24, 2016 at 12:18
  • 1
    first code will be stack overflow when run for many loop. Second is better. Commented Feb 24, 2016 at 12:26
  • The second example is actually a do {} while () loop! Commented Feb 24, 2016 at 12:36

1 Answer 1

2

Generally, the JIT is not able to replace recursion with a loop. This is a fairly esoteric optimization scenario.

Here, this does not even come into play because an async method uses very different call mechanisms internally.

This code will consume "stack space" proportional to the recursion depth. (It's not necessarily stack space with async methods. Could be heap space in the form of a linked list.)

From a code quality standpoint I find the loop vastly preferable because recursion is not what most people are used to. Here, there really is no algorithmic need for recursion. Seems like the wrong tool for the job. I think you have used recursion as a replacement for "goto" here because all this does is jump back to the beginning of the method.

You can make the jump condition a little cleaner:

        if (!_restart) break;
Sign up to request clarification or add additional context in comments.

7 Comments

the jump condition can be even cleaner than that: it's a while loop, add it to the while condition, not the end of the statement. Also, it's not returning a new task, it's firing off a new async method that may or may not be separate, I don't believe it should take more stack space at all, should it? (general question, I'm not sure in this case)
That can be done but I would not prefer it. That widens the scope of the variable and makes the conditions that control loop behavior more complicated, I think, because you have to trace the dataflow mentally across iterations.
while(_restart) explains clearly when the loop will end, when restart is set to false. while(true) will make you search the entire method for where it has a condition to break out.
Thanks a lot @usr i was looking for answer like yours from now im going to use the loop but i dont understand the part with if (!_restart) break;this messes me up i dont think it will work shouldn't there be continue instead of break ?
The Jit does often replace tail-call recursion with a loop, but 1) it's hard to predict when, 2) it's still generally still at least slightly more efficient to use an explicit loop and 3) while the code in the question has a tail call in the C#, it isn't going to compile into CIL with a tail-call because of the use of await meaning it'll be turned into a state machine to which repeated MoveNext() calls are made (as you said).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.