diff --git a/public/img/desc_thp.jpg b/public/img/desc_thp.jpg index b0c3a5b..6398c66 100644 Binary files a/public/img/desc_thp.jpg and b/public/img/desc_thp.jpg differ diff --git a/src/pages/learn/error-handling/null.mdx b/src/pages/learn/error-handling/null.mdx index d6d5035..996c793 100644 --- a/src/pages/learn/error-handling/null.mdx +++ b/src/pages/learn/error-handling/null.mdx @@ -11,19 +11,29 @@ To represent `null` we must use nullable types, represented by the question mark `?` character. For instance, a POST request may have a `username` parameter, -or it may not. This can be represented with an `String?`. +or it may not. This can be represented with an `?String`. -When we have a `Type?` we cannot use it directly. We must first +When we have a `?Type` we cannot use it directly. We must first check if the value is null, and then use it. +The syntax `?` returns `true` if the value is not null. + We must check explicitly that the value is not null. Doing @@ -36,24 +46,24 @@ To create a nullable type we must explicitly annotate the type. Other examples: String? {} +fun get_first(Array[?String] values) -> ?String {} val result = get_first([]) `} /> ## Optional chaining -If you have a `Type?` and you wish to access a field of `Type` if it exists, -you can use the optional chaining operator. +If you have a `?Type` and you wish to access a field of `Type` if it exists, +you can use the optional chaining operator `?.`. @@ -62,13 +72,41 @@ val name = person?.name - If `person` is not null, `person?.name` will return `name` +## Null unboxing + +The `!!` operator transforms a `?Type` into `Type`. + +If you are sure that a value cannot be `null`, you can force the +compiler to treat it as a regular value with the `!!` operator. +Note the two exclamation marks. + + + +You can use it to chain access: + + + +However, if at runtime you use `!!` on a null value, +the null value will be returned and your program will +blow up later. So make sure to use this operator +only when you are sure a value cannot be null. + + ## Elvis operator The Elvis operator `??` is used to give a default value in case a `null` is found. Int? {...} +fun get_score() -> ?Int {...} val test_score = get_score() ?? 0 `} /> diff --git a/src/pages/learn/error-handling/try.mdx b/src/pages/learn/error-handling/try.mdx index c09dbd3..bad72cd 100644 --- a/src/pages/learn/error-handling/try.mdx +++ b/src/pages/learn/error-handling/try.mdx @@ -12,14 +12,14 @@ and handled. ## Declare that a function returns an exception -To declare a possible error return value the `Result` enum -is used. +Possible errors have their own syntax: `Error!Type`. +This means: This may be an `Error`, or a `Type`. For example, a function that returned a `DivisionByZero` may be written like this: Int!DivisionByZero +fun invert(Int number) -> DivisionByZero!Int { if number == 0 { @@ -30,25 +30,22 @@ fun invert(Int number) -> Int!DivisionByZero } `} /> -In the previous segment, `Int!DivisionByZero` denotates -that the function may return either an `Int` or an `DivisionByZero`. +In the previous segment, `DivisionByZero!Int` denotates +that the function may return either a `DivisionByZero` error +or an `Int`. -We then can return the error or success value; +There is no `throw` keyword, errors are just returned. ### Multiple error returns -TODO: fix? +TODO: properly define syntax, how this interacts with type unions. - - -If there are multiple error types that the function can return, -you can use the `|` operator: +Multiple errors are chained with `!`. The last one is always +the success value. Int!Exceptions +fun sample() -> Error1!Error2!Error3!Int { /* ... */} `} /> @@ -68,13 +65,13 @@ Use a naked `try` when you want to rethrow an error, if there is any. Int!Exception + fun dangerous() -> Exception!Int { // May throw randomly return if Math.random() < 0.5 { 50 } else { Exception("Unlucky") } } - fun run() -> !Exception + fun run() -> Exception! { // If \`dangerous()\` throws, the function exits with the same error. // Otherwise, continues val result = try dangerous() @@ -156,7 +153,7 @@ Try/else will assign a new value if an expression fails.