|
@@ -1998,9 +1998,9 @@ relative_data_types :: proc() {
|
|
fmt.println(rel_slice[1]);
|
|
fmt.println(rel_slice[1]);
|
|
}
|
|
}
|
|
|
|
|
|
-or_else_procedure :: proc() {
|
|
|
|
|
|
+or_else_operator :: proc() {
|
|
fmt.println("\n#'or_else'");
|
|
fmt.println("\n#'or_else'");
|
|
- // IMPORTANT NOTE: 'or_else' is experimental features and subject to change/removal
|
|
|
|
|
|
+ // IMPORTANT NOTE: 'or_else' is an experimental feature and subject to change/removal
|
|
{
|
|
{
|
|
m: map[string]int;
|
|
m: map[string]int;
|
|
i: int;
|
|
i: int;
|
|
@@ -2029,6 +2029,102 @@ or_else_procedure :: proc() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+or_return_operator :: proc() {
|
|
|
|
+ fmt.println("\n#'or_return'");
|
|
|
|
+ // IMPORTANT NOTE: 'or_return' is an experimental feature and subject to change/removal
|
|
|
|
+ //
|
|
|
|
+ // The concept of 'or_return' will work by popping off the end value in a multiple
|
|
|
|
+ // valued expression and checking whether it was not 'nil' or 'false', and if so,
|
|
|
|
+ // set the end return value to value if possible. If the procedure only has one
|
|
|
|
+ // return value, it will do a simple return. If the procedure had multiple return
|
|
|
|
+ // values, 'or_return' will require that all parameters be named so that the end
|
|
|
|
+ // value could be assigned to by name and then an empty return could be called.
|
|
|
|
+
|
|
|
|
+ Error :: enum {
|
|
|
|
+ None,
|
|
|
|
+ Something_Bad,
|
|
|
|
+ Something_Worse,
|
|
|
|
+ The_Worst,
|
|
|
|
+ Your_Mum,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ caller_1 :: proc() -> Error {
|
|
|
|
+ return .None;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ caller_2 :: proc() -> (int, Error) {
|
|
|
|
+ return 123, .None;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ foo_1 :: proc() -> Error {
|
|
|
|
+ // This can be a common idiom in many code bases
|
|
|
|
+ n0, err := caller_2();
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // The above idiom can be transformed into the follow
|
|
|
|
+ n1 := caller_2() or_return;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // And if the expression has no other, it can be used like this
|
|
|
|
+ caller_1() or_return;
|
|
|
|
+ // which is functionally equivalen to
|
|
|
|
+ if err1 := caller_1(); err1 != nil {
|
|
|
|
+ return err1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _, _ = n0, n1;
|
|
|
|
+ return .None;
|
|
|
|
+ }
|
|
|
|
+ foo_2 :: proc() -> (n: int, err: Error) {
|
|
|
|
+ // It is more common that your procedure turns multiple values
|
|
|
|
+ // If 'or_return' is used within a procedure multiple parameters (2+),
|
|
|
|
+ // then all the parameters must be named so that the remaining parameters
|
|
|
|
+ // so that a bare 'return' statement can be used
|
|
|
|
+
|
|
|
|
+ // This can be a common idiom in many code bases
|
|
|
|
+ x: int;
|
|
|
|
+ x, err = caller_2();
|
|
|
|
+ if err != nil {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // The above idiom can be transformed
|
|
|
|
+ y := caller_2() or_return;
|
|
|
|
+
|
|
|
|
+ // And if the expression has no other, it can be used like this
|
|
|
|
+ caller_1() or_return;
|
|
|
|
+
|
|
|
|
+ // which is functionally equivalen to
|
|
|
|
+ if err1 := caller_1(); err1 != nil {
|
|
|
|
+ err = err1;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If a the other values need to be set depending on what the end value is,
|
|
|
|
+ // the 'defer if' is can be used
|
|
|
|
+ defer if err != nil {
|
|
|
|
+ n = -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If a non-bare return is required, then a normal if is a lot clearer
|
|
|
|
+ // and gets around the short circuiting
|
|
|
|
+ if z, zerr := caller_2(); zerr != nil {
|
|
|
|
+ n = -z;
|
|
|
|
+ err = zerr;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ n = 123;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ foo_1();
|
|
|
|
+ foo_2();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
main :: proc() {
|
|
main :: proc() {
|
|
when true {
|
|
when true {
|
|
the_basics();
|
|
the_basics();
|
|
@@ -2061,7 +2157,7 @@ main :: proc() {
|
|
union_maybe();
|
|
union_maybe();
|
|
explicit_context_definition();
|
|
explicit_context_definition();
|
|
relative_data_types();
|
|
relative_data_types();
|
|
- or_else_procedure();
|
|
|
|
|
|
+ or_else_operator();
|
|
|
|
+ or_return_operator();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-//
|
|
|