from typing import Callable


def thunkify(*args: Callable) -> Callable:
    """Creates a thunk out of a function.

    A thunk delays a calculation until its result is needed, providing lazy
    evaluation of arguments. Can be used for side effects.

    Example:
        def f(x: int):
            print("func f", x)

        def g():
            print("func g")

        val = 10
        thunk = thunkify(partial(f, val), g)
        thunk()   # prints "func f 10" and "func g"

        # Or if val won't be available till later
        thunk = thunkify(f, lambda *_: g())
        some_other_func(arg1, arg2, thunk)

        # In some_other_func
        val = 20
        thunk(val)   # prints "func f 20" and "func g"

    """
    def thunk(*_args):
        for a in args:
            a(*_args)
    return thunk