高校物理160203 views
高校国語788336 views
いろは3010814 views
中学社会668760 views
雑学1473612 views
高校日本史190571 views
ヒストリア290598 views
英語613639 views
小学社会310485 views
小学理科719870 views
Help
Tools
NewsSpreadsheetCalendarBookkeepingSlidesTier ListPen ToolIllustrationCrayonWatercolorPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchSwirl EffectLine ArtOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsRolling DiceCross SectionsMotion PathMechanicsWavesElectromagnetic WavesCapacitorsLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHOrganic Reaction MapPeriodic TableComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseMuscle ContractionHormones and HomeostasisRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic TheoryShogi StrategyPiano Rhythm Game

English

Python のトランポリン(末尾再帰の手動最適化)

トランポリンは末尾再帰をループに変換し、スタックオーバーフローを防ぐ手法です。Python は末尾再帰最適化をしないため、深い再帰にはこの技法が有効です。

問題の再確認

def factorial(n, acc=1):
    if n <= 1:
        return acc
    return factorial(n - 1, acc * n)

factorial(10000)  # RecursionError

末尾再帰の形でも、Python ではスタックを消費します。

トランポリンの仕組み

関数が直接再帰呼び出しする代わりに、「次に呼び出すべき関数」を返します。トランポリン関数がこれをループで実行します。

class Thunk:
    def __init__(self, func, *args, **kwargs):
        self.func = func
        self.args = args
        self.kwargs = kwargs

def trampoline(func, *args, **kwargs):
    result = func(*args, **kwargs)
    while isinstance(result, Thunk):
        result = result.func(*result.args, **result.kwargs)
    return result

トランポリン対応の階乗

def factorial_t(n, acc=1):
    if n <= 1:
        return acc
    return Thunk(factorial_t, n - 1, acc * n)

result = trampoline(factorial_t, 10000)
print(len(str(result)))  # 35660 桁

RecursionError なしで計算できます。

デコレータ化

def trampolined(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        while isinstance(result, Thunk):
            result = result.func(*result.args, **result.kwargs)
        return result
    return wrapper

@trampolined
def fib_t(n, a=0, b=1):
    if n == 0:
        return a
    return Thunk(fib_t, n - 1, b, a + b)

print(fib_t(10000))  # 巨大なフィボナッチ数

ジェネレータを使った方法

def trampoline_gen(gen):
    stack = [gen]
    result = None
    while stack:
        try:
            item = stack[-1].send(result)
            if hasattr(item, "__next__"):
                stack.append(item)
                result = None
            else:
                result = item
        except StopIteration as e:
            stack.pop()
            result = e.value
    return result

トランポリンは再帰的アルゴリズムを Python で安全に実行する実用的なパターンです。