local $Y = sub {
    local ($h) = @_;
    sub { local ($x) = @_; $x->($x) }->(
        sub {
            local ($g) = @_;
            $h->(sub { local @args = @_; $g->($g)->(@args) })
        }
    )
};

local $trampoline = sub {
    local ($f) = @_;
    sub {
        local @args = @_;
        local $result = $f->(@args);
        while (ref($result) eq 'CODE') {
            $result = $result->();
        }
        $result
    }
};

local $fac = sub {
    local ($n) = @_;
    $trampoline->(
        $Y->(sub {
            local ($f) = @_;
            sub {
                local ($n, $acc) = @_;
                $n == 0
                    ? $acc
                    : sub { $f->($n - 1, $n * $acc) }
            }
        })
    )->($n, 1)
};

print $fac->(5), "\n";