NAME
    Context::Vars - variables with context scope

VERSION
    Version 0.03

SYNOPSIS
        use Context::Vars q{$variable};

        $variable = 'one';

        sub change {
            $variable = 'two';
            print $variable;    # two
        }

        change();

        print $variable;    # one

        # A callback run later sees the values of the moment it was wrapped.
        sub handle {
            my ($id) = @_;
            $variable = $id;
            return Context::Vars->wrap(sub { print "$variable\n" });
        }

        my $later = handle('request 42');
        $later->();      # request 42

DESCRIPTION
    A name given to "use" becomes a scalar in the calling package. Every
    package that imports the same name shares the one variable, and what it
    reads is the value in the context that is current at that moment.

    An assignment to the variable holds until the sub it is written in
    returns, through any block in that sub and any way out of it, and is
    seen by every sub that sub calls. Code outside any sub keeps what it
    assigns for the program.

    A callback wrapped with "wrap", or run with "run" in
    Context::Vars::Context, sees the values of the moment it was wrapped or
    captured, wherever and whenever it runs: from an event loop, after other
    work has changed them, or after other requests have come and gone.

ARRAYS, HASHES AND STRUCTURES
        use Context::Vars qw(@trail %seen $config);

    Arrays and hashes are imported as scalars are, and follow the same rule:
    a change to one, an element stored or deleted, a "push", a whole
    assignment, holds until the sub it is written in returns.

    The rule goes all the way down. A plain hash or array stored in any
    context variable, at any depth, belongs to the context: "$seen{a}{b} =
    1", "push @{ $seen{list} }, 1" or "$config->{db}{host} = 'x'" in a sub
    is undone when that sub returns, and a capture or a wrapped callback
    sees the structure as it was at that moment. What is stored is the
    variable's own copy: changing the hash or array that was assigned does
    not change the variable, and the other way round.

    An object, or a code reference, stored anywhere in such a structure is
    kept as the reference it is, and what it points at is shared, as its
    class expects.

    What you read back is not the hash or array that was stored but one that
    stands for it: "ref" says "HASH" or "ARRAY" and everything a hash or
    array does works, but two reads of $seen{a} are two different
    references, and "==" between them is false. Copy one out, "{ %{ $seen{a}
    } }", for an ordinary hash.

    Reading or writing an element costs more than it does in an ordinary
    hash or array: some hundreds of nanoseconds against some tens, and more
    for each level down.

LIMITS
    *   Names are plain identifiers: $name, @name, %name.

    *   No event loop captures for you. A callback sees its registering
        code's values only when it is wrapped; see "CALLBACKS AND LOOPS".

    *   An assignment the module cannot see when the sub is compiled is not
        scoped to that sub. That is one made through @_, a "for", "grep" or
        "map" alias, a symbolic reference, a string "eval" inside a sub that
        makes no other assignment, or a hash or array read out of a variable
        and kept in a lexical before it is written through: "my $h =
        $seen{a}; $h->{b} = 1". It changes whatever context is current.

    *   A sub that only assigns a variable for its caller changes nothing
        the caller can see: the assignment ends when that sub returns.
        Return the value and let the caller assign it.

CALLBACKS AND LOOPS
    A callback that runs later, from an event loop, a queue or a future,
    sees the values of the moment it was registered only if whatever
    registered it captured them. "wrap" does that for one callback. A loop
    that does it for every callback it keeps is said to be wired.

    A callback on a loop that is not wired runs outside any context. There a
    variable reads nothing, unless code outside any sub has assigned it, in
    which case it reads that value: never the value of the task that
    registered the callback.

ASYNC SUBS
    Under Future::AsyncAwait, an "async sub" keeps its own variables across
    "await": after the await it reads what it could see before it, and what
    it assigns is not seen by the code that resumed it. This needs nothing
    from Future::AsyncAwait to install, and works whichever of the two
    modules is loaded first.

METHODS
    These are for code that runs other code later: an event loop, a queue, a
    future, a test. An application that only reads and assigns its variables
    does not need them.

  capture
        my $ctx = Context::Vars->capture;

    Returns a Context::Vars::Context holding the values every variable has
    now. Later assignments, here or anywhere, do not change what it holds.

  wrap
        my $callback = Context::Vars->wrap(sub { ... });

    Returns a code reference that calls the given one with the values every
    variable has now, wherever and whenever it is called. Its arguments are
    passed through and its return value is returned. Each call starts from
    those values afresh: nothing one call does is seen by the next.

  current
        my $ctx = Context::Vars->current;

    Returns a Context::Vars::Context for the context code is running in now,
    rather than a copy of it. Code run in it with "run" in
    Context::Vars::Context and the code running now share their values.

C ABI
    An event loop, a future or a queue written in C can capture the
    variables when a callback is registered and run the callback with them,
    and C code can read and assign a variable by name, with no Perl call in
    between. The header, context_vars_abi.h, is installed with this module
    and found through ExtUtils::Depends; it describes the table of
    functions, how to find it at run time, and the three calls a loop makes
    for each callback. A consumer needs that header and nothing else.

DEPENDENCIES
    HAMT. Loading this module fails, with a message that says why, when HAMT
    is not installed or is too old.

AUTHOR
    LNATION <email@lnation.org>

BUGS
    Please report any bugs or feature requests to "bug-context-vars at
    rt.cpan.org", or through the web interface at
    <https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Context-Vars>.

LICENSE AND COPYRIGHT
    This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

    This is free software, licensed under:

      The Artistic License 2.0 (GPL Compatible)

