New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Throw Statements cannot be used as expressions #432
Comments
This is a general problem with throw "expressions": let x = throw new RuntimeException
print(throw new RuntimeException) |
TypeScript (and probably other languages) solve this by introducing a
They also use it for dead-code detection (this is not directly tied to the exception stuff, but plays well with it. It also requires control-flow based type checking): const x = "foo"
if (x === "foo") {
//....
} else {
// x is of type never
} Using this never construct, you can also assert that the cases of a switch statement are exhaustive during type checking: function assertNever(value: never) {}
//...
const x = "foo";
switch(x)
{
case "foo":
return "bar";
default: assertNever(x); // if there is a code path that would hit the default branch, x would not be never but something diffferent instead. This errors at compile time
} C# does not have this but allows void Test(string arg) {
this.Arg = arg ?? throw new ArgumentNullException();
}
string GetLastName()
{
var parts = Name.Split(' ');
return parts.Length > 1 ? parts[1] : throw new InvalidOperationException("Invalid name!");
} It also helps when using lambdas in some cases: void Test2() {
SomeFunctionWithCallback(() => throw new NotImplementedException());
var foo = "bar";
var a = foo switch { // Switch expressions
"bar" => "baz",
_ => throw new NotSupportedException()
}
} Maybe this inspires you. The way Java does it (making throw a statement only) is not the only way of handling this case. Java recently tries to work around this decision by selectively allowing "throw" statements in the new pattern matching proposal. This wouldn't have been necessary if they did it different in the first place. |
Hm, actually I already have a type like |
I'm curious: Whats the difference to something like It seems that it is exactly the same as never (but without trivial infinite loop detection). It confused me because some languages use "none" when they mean something like "void". |
Well the type system treats it differently because it is a bottom type. Also, it makes the difference between „function f():void returns nothing“ and „function g():none never returns at all“. Indeed the naming is confusing, I should rename it to |
I think my phrasing was ambiguous (corrected now). It actually is the same as never in TS, but without trivial infinite loop detection (and unreachable code detection in general?). Other languages use "none" as a unit type. I first had the impression that it was the same here. Thanks for clarification. |
Yes, there is no unreachable code detection at all in the language. The compiler is not sophisticated enough for that and retrofitting it is a pain. |
The following REPL input causes a compiler error:
The reason is that the REPL tries to assign the expression to a field, but the expression does not return.
The text was updated successfully, but these errors were encountered: