ScopedValue: Capturing current bindings

Attila Kelemen attila.kelemen85 at gmail.com
Thu Jun 1 11:58:49 UTC 2023


> ... we don't support gotos in Java ...

I don't think goto is a good comparison, because goto doesn't need to
be supported, since - even for cases when it would be useful - it is
trivial to workaround. However, the problem I wrote down is different,
because the current constructs prevent any solution.

Let me rephrase the problem: Consider that a hypothetical (simplistic)
SV based DI framework supports lazily created singleton resources (and
it will close them, if they were actually created). For example (with
my originally described micro API):

```
/* 01 */ ScopedValue<String> testValue = ScopedValue.newInstance();
/* 02 */
/* 03 */ ScopedValue.where(testValue, "OuterValue", () -> {
/* 04 */   withBinding(MyResource.class, this::getLazyMyResource, () -> {
/* 05 */     ScopedValue.where(testValue, "InnerValue", () -> {
/* 06 */       System.out.println("1: " + getByType(MyResource.class));
/* 07 */     });
/* 08 */     System.out.println("2: " + getByType(MyResource.class));
/* 09 */   });
/* 10 */ });
```

In line (4), the application knows that we are in a well-defined
context (by its nature, there is exactly one point where you are
binding the factory `MyResources`). However, you don't know where it
will be queried (if it is at all), and especially don't know where it
will be queried the first time (you would not use a lazy construct
otherwise). That said, a reasonable DI framework wants to define a
consistent well-defined behaviour. However, as it stands now, it is
impossible, because it cannot guarantee a consistent context for the
`getLazyMyResource` call. For example, if I added a
`getByType(MyResource.class)` call between (4) and (5), then that
would change the behaviour of the code, if the resource depends on the
value of `testValue`. This would be a completely unacceptable
behaviour, and - as far as I know - there is no way to workaround
this. That is, the current limitations on SV scope handling disallow
APIs from exhibiting consistent behaviour, if they don't want to know
the context where their own SV is being access from. (there are even
more limitations of SV, but first I wanted to focus on this issue,
since this is the simplest case)


> However, any structure that allows a scoped value to live after its binding scope has terminated is out of the question because it breaks a fundamental invariant.

I do not want this at all, and never suggested to have this
possibility. In fact, I agree that such access should not be allowed.


More information about the loom-dev mailing list