Scoped variables: a rough first draft

Andrew Haley aph at redhat.com
Wed Aug 21 15:42:16 UTC 2019


Here's my thinking:


In a (very) abstract world, we'd want something like

class MyHolderClass {
   scoped X myVar;
}

which provides a name for a variable but allocates no storage for it.

Note that all of the usual Java access rules apply. If the declaration
of MyHolderClass.myVar isn't accessible, neither are any of its bound
values.

When we want to use one of these variables, we'll first have to bind
it to some storage. I suggest something like this:

   {
        bind myVar;
        ...
        ... invocations ...
        ...
   }

At this point the variable has a binding, but has not not been
assigned a value. Conceptually, this scoped variable's value now has a
storage location but has no value.

>From this point onwards, accesses to MyHolderClass.myVar will refer to
the innermost bound binding. Assignments to unbound scoped variables
will raise an exception.

Note that the scope search order is *dynamic*. So, if we have a bunch
of nested continuations, the binding used is the innermost one that is
found in the current stack. So, if a carrier thread binds a scoped
variable, it will be visible to all continuations running on that
stack.

So why search the dynamic scopes, not the scopes in existence when the
continuations where created? Two reasons:

1. We can't guarantee that the creation-time binding scope will still
exist when the continuation is executed.

2. If we need continuations to inherit from the context at creation
time, we already have mechanisms to do that. What we don't have is a
way to access the dynamic scope, which is what this mechanism
provides.

I'm writing a rough (and very inefficient) patch which does something
like this, albeit in a not-very-efficient way. Here's what it looks
like.

The declaration of a scoped variable is

class MyHolderClass {
    static final ScopedVariable<X> myVar = ScopedVariable.forType(X.class);
}

To create a binding I've used try-with-resources:

   try (ScopedVariableBinding<X> b = myVar.bind()) {
        ...
        ... invocations ...
        ...
   }

And in place of assignments and accesses,

   myVar.get(), myVar.set()

There are some weaknesses in this approximation of the abstract idea,
in particular that we can't enforce the binding scope. But never mind,
that can be fixed later. The (lack of) efficiency can be fixed too.

So, he says with some trepidation, is this basically sane?  :-)

-- 
Andrew Haley  (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
https://keybase.io/andrewhaley
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671


More information about the loom-dev mailing list