Maintenant que C# a Local Functions, le Bowling Game coding kata peut être élégamment résolu avec un trampoline :
using System.Collections.Generic;
using System.Linq;
class Game
{
internal static int RollMany(params int[] rs)
{
return Trampoline(1, 0, rs.ToList());
int Trampoline(int frame, int rsf, IEnumerable rs) =>
frame == 11 ? rsf
: rs.Count() == 0 ? rsf
: rs.First() == 10 ? Trampoline(frame + 1, rsf + rs.Take(3).Sum(), rs.Skip(1))
: rs.Take(2).Sum() == 10 ? Trampoline(frame + 1, rsf + rs.Take(3).Sum(), rs.Skip(2))
: Trampoline(frame + 1, rsf + rs.Take(2).Sum(), rs.Skip(2));
}
}
La méthode Game.RollMany
est appelée avec un nombre de lancers : généralement 20 lancers s'il n'y a pas de spare ou de strike.
La première ligne appelle immédiatement la fonction trampoline : return Trampoline(1, 0, rs.ToList());
. Cette fonction locale traverse récursivement le tableau de lancers. La fonction locale (le trampoline) permet au parcours de commencer avec deux valeurs supplémentaires : commencer avec le frame
1 et le rsf
(résultat jusqu'à présent) 0.
À l'intérieur de la fonction locale, il y a un opérateur ternaire qui gère cinq cas :
- La partie se termine au frame 11 : retourne le résultat jusqu'à présent
- La partie se termine s'il n'y a plus de lancers : retourne le résultat jusqu'à présent
- Strike : calcule le score du frame et continue le parcours
- Spare : calcule le score du frame et continue le parcours
- Score normal : calcule le score du frame et continue le parcours
La poursuite du parcours se fait en appelant de nouveau le trampoline, mais maintenant avec des valeurs mises à jour.
Pour plus d'information, recherchez : "tail recursion accumulator". Gardez à l'esprit que le compilateur n'optimise pas la récursion terminale. Donc aussi élégante que cette solution puisse être, elle ne sera probablement pas la plus rapide.
2 votes
Dans le monde Microsoft, les trampolines sont généralement appelés "thunks". [Voici une page](http://books.google.com/books?id=aJ1av7UFBPwC&pg=PA280&lpg=PA280&dq=thunk+trampoline&source=web&ots=YQcG0nOf7Z&sig=PZA-Pbx19C9Mnw\_1myezK4x3QWQ&hl=en&sa=X&oi=book\_result&resnum=4&ct=result) tirée du livre "Modern C++ Design" d'Andrei Alexandrescu.
1 votes
Lié
0 votes
C'est essentiellement la forme généralisée de certaines fonctionnalités que vous pourriez implémenter avec setjmp/longjmp, à savoir éviter le dépassement de pile.
26 votes
Pourquoi quelqu'un voudrait-il éviter Stack Overflow ?