rockclimber,
worm2, поверьте, даже для автора подобный код начинает выглядеть как китайская грамота после непродолжительной разлуки с ним.
В самом простом случае, когда в
reset передан некий
functor и только один
shift, код аналогичен простому вызову
shift(functor) (ветка
else в
if constexpr). Точнее,
functor перед передачей завертывается в лямбду, но это не имеет значения. Когда число переданных
shiftов более одного, из остальных
shiftов (
other_shifts) и самого
reset конструируется функтор, который передается в первый
shift. При этом передаваемый во внутренний
reset функтор получается из исходного
functor фиксацией нескольких первых аргументов, используемых первым
shiftом (скорее всего, для нужд первого
shiftа надо было оставить только один аргумент).
Кажется, объяснение получилось еще непонятнее, чем сам код.
arseniivВ предположении, что это то, как перевести выражение
reset (2 * shift (\continue -> 17 + continue 4))
(должно давать 25)?
const auto result =
reset([](auto&& shift) { return 2 * shift; }, [](auto&& functor) { return 17 + functor(4); });
std::cout << result << std::endl;
Вы
это хотели увидеть? Или что-то другое имели в виду?
-- Пт май 04, 2018 10:36:56 --arseniivМожно реализовать и пример с
try ... catch ... оттуда же:
try (17 + throw 4) catch (\e -> 42 + e),
где
try ... catch ... и
throw определяются так:
throw e = escape (\_ -> (\h -> h e))
try a catch h = (capture (let x = a in \_ -> x)) hРеализация на C++17 с использованием ранее написанного
reset:
const auto make_throw = [](auto exception) {
return [exception = std::move(exception)](auto&&) {
return [exception = std::move(exception)](auto&& handler) { return handler(exception); };
};
};
auto try_catch = [](auto&& try_, auto&& catch_, auto&&... exceptions) {
if constexpr (sizeof...(exceptions) > 0)
{
return reset(try_, make_throw(std::forward<decltype(exceptions)>(exceptions))...)(catch_);
}
else
{
return try_();
}
};
// ...
const auto result_exception_thrown = try_catch(
[](auto&& throw_) { return 17 + throw_; }, [](auto&& exception) { return 42 + exception; }, 4);
const auto result_no_throw =
try_catch([] { return 17; }, [](auto&& exception) { return 42 + exception; });
std::cout << "An exception is thrown: " << result_exception_thrown << std::endl;
std::cout << "No throw: " << result_no_throw << std::endl;
Собственно, тут хорошо видны ограничения моего подхода.