def xloop(
    max_iter: Optional[Var] = None,
    start_loop: Optional[Var] = None,
    initial: Sequence[Var] = (),
    *,
    fun: Callable[..., Iterable[Var]],
) -> Sequence[Var]:
    """
    Simplified constructor for the Loop operator.

    Instead of a Graph this constructor takes ``fun``, which should
    take 2+N Var arguments and 1+N+K Var results.

    - The first two arguments are 1-vectors for (int64) iteration and (boolean) stop condition.
    - The first result is a 1-vector (boolean) for the next stop condition.
    - N: *carried* values. Carried from previous iteration (or initial). The last carried outputs are stored in the first element of the returned tuple.
    - K: *scanned* values. All such outputs must be Tensors, and they are concatenated. They are stored in the second element of the returned tuple.

    Note that ``fun`` may use values from the outer scope,
    but to make sure they defined in the outer scope (instead of inlined in the inner scope) they
    should be marked with ``intro(*outer, loop(...))``.

    For the details of Loop behaviour, see the docstring for loop.
    """
    if max_iter is not None:
        max_iter = reshape(max_iter, const([1]))
    if start_loop is not None:
        start_loop = reshape(start_loop, const([1]))
    return loop(max_iter, start_loop, initial, body=subgraph(
        typing_cast(List[Type], [Tensor(np.int64, (1,)), Tensor(np.bool_, (1,))])
        + [var.unwrap_type() for var in initial],
        fun
    ))
