Browse Source

Add `or_return_operator` to examples/demo

gingerBill 4 years ago
parent
commit
ac08d37ca0
1 changed files with 100 additions and 4 deletions
  1. 100 4
      examples/demo/demo.odin

+ 100 - 4
examples/demo/demo.odin

@@ -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();
 	}
 	}
 }
 }
-//