-module(defer). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([defer/2, start_defer/2, add_defer/3]). -export_type([defer_context/0]). -opaque defer_context() :: {defer_context, list(fun(() -> nil))}. -spec defer(fun(() -> any()), fun(() -> HFC)) -> HFC. defer(Defer_func, Rest) -> Result = Rest(), Defer_func(), Result. -spec new_context() -> defer_context(). new_context() -> {defer_context, []}. -spec append_to_context(defer_context(), fun(() -> nil)) -> defer_context(). append_to_context(Context, New_defer_func) -> {defer_context, Previous} = Context, {defer_context, [New_defer_func | Previous]}. -spec run_defers(list(fun(() -> nil))) -> nil. run_defers(Defers) -> case Defers of [] -> nil; [One] -> One(); [One@1 | Rest] -> run_defers(Rest), One@1() end. -spec start_defer( fun(() -> nil), fun((defer_context()) -> {defer_context(), HFG}) ) -> HFG. start_defer(Defer_func, Rest) -> Context = begin _pipe = new_context(), append_to_context(_pipe, Defer_func) end, {{defer_context, Defers}, Result} = Rest(Context), run_defers(Defers), Result. -spec add_defer( defer_context(), fun(() -> nil), fun((defer_context()) -> {defer_context(), HFH}) ) -> {defer_context(), HFH}. add_defer(Context, Defer_func, First) -> Context@1 = append_to_context(Context, Defer_func), First(Context@1).