Why does `ScopedValue.where(SCOPE_VALUE, val).call()` throw Exception?

Kasper Nielsen kasperni at gmail.com
Fri Mar 24 11:15:17 UTC 2023


On Fri, 24 Mar 2023 at 09:59, Andrew Haley <aph-open at littlepinkcloud.com> wrote:
> Surely you could write something like
>
>      public static <T> T call(ScopedValue.Carrier aCarrier, Callable<T> aCallable) {
>         try {
>           return aCarrier.call(aCallable);
>         } catch (RuntimeException e) {
>           throw e;
>         } catch (Exception e) {
>       throw new UndeclaredThrowableException(e);
>     }
>
> ... and then use it everywhere as
>
>     return call(ScopedValue.where(s, value), callable);
>
> ... or even wrap the ScopedValue.Carrier class to give you exactly what you need.
>

Sure, it will probably end up in a reusable class somewhere.
I just tested it out in a couple of separate small projects that
didn't share any code. And most of the places I didn't have any
need for the checked version. Just posting my observation.

Regarding the issue on handling of Throwable instead of plain Exception.
This still feels a bit clunky if you are unable to handle it inside the scope.
What I got is

interface ThrowingSupplier<R> { //Could be <R,T extends Throwable>
    R get() throws Throwable;
}

public static <T, R> R where(ScopedValue<T> key, T value,
ThrowingSupplier<? extends R> op) throws Throwable {
  record Result<R>(R result, Throwable failure) {}
  Result<R> result = ScopedValue.where(key, value).call(() -> {
    try {
      return new Result<>(op.get(), null);
    } catch (Throwable e) {
      return new Result<>(null, e);
    }
  });
  if (result.failure != null) {
    throw result.failure;
  }
  return result.result;
}

It is definitely doable but doesn't feel right.

/Kasper


More information about the loom-dev mailing list