<div dir="auto">What you are trying to do is possible to implement, albeit a bit convoluted and wasteful.<div dir="auto"><br></div><div dir="auto">Ignoring all of the details, conceptually ScopedValues are made out of 2 parts: </div><div dir="auto"><br></div><div dir="auto"> - The instances</div><div dir="auto"> - The bindings</div><div dir="auto"><br></div><div dir="auto">You create instances, bind them to values, and run some code under the spe cific bindings.</div><div dir="auto"><br></div><div dir="auto">So to get the functionality you are looking for you need to wrap the SV instances with your own object "AwareScopedValue", ASV will hold onto a list of SV, when you bind a new value you can either override the top SV, or create a new SV and put it on the top of the stack.</div><div dir="auto"><br></div><div dir="auto">When binding a ASV you simply bind all of the SV.</div><div dir="auto"><br></div><div dir="auto">When trying to get value from it, you can choose from which layer to take.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">---</div><div dir="auto"><br></div><div dir="auto">But I'm not sure you really need this functionality, having a public SV is just begging for problems so *any* use of SV should be transparent to the user, and inside of your own library/framework you can make sure that are no double-bindings, and if you need several layers of bindings, then your use case is not what a single SV is meant to handle.</div><div dir="auto"><br></div><div dir="auto">Cheers,</div><div dir="auto">Yuval Paz </div><div dir="auto"><br></div><div dir="auto"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 23, 2023, 17:07 Attila Kelemen <<a href="mailto:attila.kelemen85@gmail.com">attila.kelemen85@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I was contemplating on a dependency injection framework built on<br>
scoped values. For the sake of simplicity, I will make it trivial and<br>
unoptimized here. Consider the following as our mini limited DI<br>
framework:<br>
<br>
```<br>
ScopedValue<Map<Class<?>, Supplier<?>>> FACTORIES<br>
    = ScopedValue.newInstance();<br>
<br>
<T> void withBinding(<br>
    Class<T> type,<br>
    Supplier<T> supplier,<br>
    Runnable task<br>
) {<br>
  var prevValue = FACTORIES.orElse(Collections.emptyMap());<br>
  var newValue = new HashMap<>(prevValue);<br>
  newValue.put(type, supplier);<br>
<br>
  ScopedValue.where(FACTORIES, newValue, task);<br>
}<br>
<br>
<T> T getByType(Class<T> type) {<br>
  Supplier<?> provider = FACTORIES<br>
      .orElse(Collections.emptyMap())<br>
      .get(type);<br>
  if (provider == null) {<br>
    throw new IllegalStateException();<br>
  }<br>
  return type.cast(provider.get());<br>
}<br>
```<br>
<br>
A trivial use of such framework would look like this:<br>
<br>
```<br>
withBinding(String.class, () -> "Hello!", () -> {<br>
  System.out.println(getByType(String.class));<br>
});<br>
```<br>
<br>
This would print "Hello!" as expected. However, consider the following case:<br>
<br>
```<br>
ScopedValue<String> testValue = ScopedValue.newInstance();<br>
<br>
ScopedValue.where(testValue, "OuterValue", () -> {<br>
  withBinding(String.class, testValue::get, () -> {<br>
    ScopedValue.where(testValue, "InnerValue", () -> {<br>
      System.out.println(getByType(String.class));<br>
    });<br>
  });<br>
});<br>
```<br>
<br>
While we would normally expect the injection to be uninfluenced by the<br>
calling context (especially, since you could even use this for lazy<br>
singletons). However, the above would obviously print "InnerValue",<br>
even though that was not the case when calling `withBinding`.<br>
<br>
This is because we can't capture the bindings (at least I don't know a<br>
way). Not even StructuredTaskScope can be (ab)used for this, because<br>
it would (rightfully) refuse the `fork`, if the current scoped value<br>
context changed.<br>
<br>
What I wish for is a way to capture the current scoped values, and<br>
later execute code with the captured scoped values. For example, we<br>
could have a `ScopedValues.withCurrentContext(Consumer<CapturedScopedValueContext>)`<br>
(or similar , variants), where `CapturedScopedValueContext` could look<br>
like this (simplified for clarity):<br>
<br>
```<br>
interface CapturedScopedValueContext {<br>
  <T> T inContext(Callable<? extends T> task);<br>
}<br>
```<br>
<br>
in which case, now we could create our safe `withBinding` variant<br>
relying on the current unsafe version:<br>
<br>
```<br>
<T> void withBindingSafe(<br>
    Class<T> type,<br>
    Supplier<T> supplier,<br>
    Runnable task<br>
) {<br>
  ScopedValues.withCurrentContext(context -> {<br>
    withBinding(type, () -> context.inContext(supplier::get), task);<br>
  });<br>
}<br>
```<br>
<br>
Replacing `withBinding` with `withBindingSafe` in our "complicated"<br>
use-case, we would receive "OuterValue" as intended.<br>
<br>
I hope we can have something like this or similar feature (obviously<br>
not in JDK 21) enabling this use-case.<br>
<br>
Attila<br>
</blockquote></div>