Skip to content

Instantly share code, notes, and snippets.

@jackfirth
Created June 30, 2022 21:43
Show Gist options
  • Save jackfirth/d22dc4ea592ac39d76739f665eb7bbf8 to your computer and use it in GitHub Desktop.
Save jackfirth/d22dc4ea592ac39d76739f665eb7bbf8 to your computer and use it in GitHub Desktop.
class Map<K, V> {
   ...

    V getOrSignal(K key) {
        if containsKey(key) {
            return get(key);
        } else {
            MissingKeySignal signal = throw new MissingKeyException(this, key);
            return switch signal {
                case ReturnValueSignal(value) -> defaultValue,
                case PutAndReturnValueSignal(value) -> {
                    put(key, value);
                    return value;
                },
                case TryAnotherKeySignal(otherKey) -> getOrSignal(otherKey)
            }
        }
    }
}

class MissingKeyException<K, V> extends ResumableException<MissingKeySignal<K, V>> { ... }

sealed interface MissingKeySignal<K, V> permits ReturnValueSignal, PutAndReturnValueSignal, TryAnotherKeySignal {}
record ReturnValueSignal<K, V>(V defaultValue) implements MissingKeySignal<K, V> {}
record PutAndReturnValueSignal<K, V>(V value) implements MissingKeySignal<K, V> {}
record TryAnotherKeySignal<K, V>(K otherKey) implements MissingKeySignal<K, V> {}


class MyVideogameApp {
    public static void main(String... args) {
        try {
            ...
        } catch resumably (MissingKeyException e) {
            ... show exception to user, ask for what signal they want to send back ...
            ... this could show a GUI dialog instead of printing to the console and reading input ...
            MissingKeySignal response = printExceptionAndAskForMissingKeyResponseSignal(e);
            resume response; // resume at the point the exception was thrown, sending response as the signal
            // if the resume keyword isn't called, the exception propagates as usual
            // any catch blocks with resume statements in them prevent finally blocks from running until after
            // it's known whether or not the exception will fatally throw or not.
            // if the exception is rethrown, all paused finally blocks execute.
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment