{"action":"created","issue":{"url":"https://api.github.com/repos/vavr-io/vavr/issues/2137","repository_url":"https://api.github.com/repos/vavr-io/vavr","labels_url":"https://api.github.com/repos/vavr-io/vavr/issues/2137/labels{/name}","comments_url":"https://api.github.com/repos/vavr-io/vavr/issues/2137/comments","events_url":"https://api.github.com/repos/vavr-io/vavr/issues/2137/events","html_url":"https://github.com/vavr-io/vavr/issues/2137","id":264551436,"number":2137,"title":"Why are Checked* classes declared to throw Throwable","user":{"login":"mrpotes","id":959542,"avatar_url":"https://avatars0.githubusercontent.com/u/959542?v=4","gravatar_id":"","url":"https://api.github.com/users/mrpotes","html_url":"https://github.com/mrpotes","followers_url":"https://api.github.com/users/mrpotes/followers","following_url":"https://api.github.com/users/mrpotes/following{/other_user}","gists_url":"https://api.github.com/users/mrpotes/gists{/gist_id}","starred_url":"https://api.github.com/users/mrpotes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrpotes/subscriptions","organizations_url":"https://api.github.com/users/mrpotes/orgs","repos_url":"https://api.github.com/users/mrpotes/repos","events_url":"https://api.github.com/users/mrpotes/events{/privacy}","received_events_url":"https://api.github.com/users/mrpotes/received_events","type":"User","site_admin":false},"labels":[{"id":348730519,"url":"https://api.github.com/repos/vavr-io/vavr/labels/question","name":"question","color":"ff6600","default":true}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":14,"created_at":"2017-10-11T11:31:26Z","updated_at":"2017-11-08T10:02:57Z","closed_at":"2017-11-08T00:03:58Z","author_association":"NONE","body":"All `Throwable` instances must either be an `Exception` or an `Error`. The javadoc for `Error` states that:\r\n\r\n> An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch.\r\n\r\nHowever, because Vavr lambda classes generally declare to throw `Throwable`, developers end up writing this sort of thing:\r\n\r\n```java\r\npublic void doSomething(CheckedRunnable thing) throws MyException {\r\n  try {\r\n    thing.run();\r\n  } catch (SomeExpectedException e) {\r\n     // recover/log/rethrow/whatever\r\n  } catch (Throwable e) { // have to catch because CheckedRunnable declares to throw\r\n    throw new IllegalStateException(\"I only expected SomeExpectedException\", e);\r\n  }\r\n}\r\n```\r\n\r\nBut we've now ended up with any `Error` being caught and handled by the application. Obviously this can be fixed by doing something like:\r\n\r\n```java\r\n  } catch (Exception e) {\r\n    throw new IllegalStateException(\"I only expected SomeExpectedException\", e);\r\n  } catch (Throwable t) {\r\n    throw (Error) t; // we know this must now be an Error\r\n  }\r\n```\r\n\r\nBut as `Error` doesn't have to (or indeed, based on the javadoc, shouldn't) be caught, we really shouldn't have to be doing this.\r\n\r\nThis would be avoided if the `Checked*` signatures instead were:\r\n\r\n```java\r\n@FunctionalInterface\r\npublic interface CheckedRunnable {\r\n    void run() throws Exception;\r\n}\r\n```\r\n\r\nAnd the resulting calling code would be safer.\r\n\r\nAside: I'd actually prefer that the signatures were something like:\r\n\r\n```java\r\n@FunctionalInterface\r\npublic interface CheckedRunnable<E extends Exception> {\r\n    void run() throws E;\r\n}\r\n```\r\n\r\nor perhaps, to remind users that a lambda may throw a `RuntimeException`:\r\n\r\n```java\r\n@FunctionalInterface\r\npublic interface CheckedRunnable<E extends Exception> {\r\n    void run() throws E, RuntimeException;\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/vavr-io/vavr/issues/comments/342769136","html_url":"https://github.com/vavr-io/vavr/issues/2137#issuecomment-342769136","issue_url":"https://api.github.com/repos/vavr-io/vavr/issues/2137","id":342769136,"user":{"login":"mrpotes","id":959542,"avatar_url":"https://avatars0.githubusercontent.com/u/959542?v=4","gravatar_id":"","url":"https://api.github.com/users/mrpotes","html_url":"https://github.com/mrpotes","followers_url":"https://api.github.com/users/mrpotes/followers","following_url":"https://api.github.com/users/mrpotes/following{/other_user}","gists_url":"https://api.github.com/users/mrpotes/gists{/gist_id}","starred_url":"https://api.github.com/users/mrpotes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mrpotes/subscriptions","organizations_url":"https://api.github.com/users/mrpotes/orgs","repos_url":"https://api.github.com/users/mrpotes/repos","events_url":"https://api.github.com/users/mrpotes/events{/privacy}","received_events_url":"https://api.github.com/users/mrpotes/received_events","type":"User","site_admin":false},"created_at":"2017-11-08T10:02:57Z","updated_at":"2017-11-08T10:02:57Z","author_association":"NONE","body":"Perhaps I could challenge you to give an example that shows why `Throwable` is actually required in vavr, where `Exception` would not be sufficient?"}}
{"actor":{"display_login":"mrpotes"}}