From b4497d88e9a910481dc848a3acc93686d543efcb Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Thu, 28 Feb 2019 20:59:17 -0600 Subject: [PATCH] FEATURE: Add an or operation on the maybe module type. --- docsite/site/content/stdlib/functional.md | 10 +++++++++- std/functional.ucg | 9 ++++++++- std/tests/functional_test.ucg | 10 ++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/docsite/site/content/stdlib/functional.md b/docsite/site/content/stdlib/functional.md index e2b5a46..0f16bcf 100644 --- a/docsite/site/content/stdlib/functional.md +++ b/docsite/site/content/stdlib/functional.md @@ -16,6 +16,14 @@ UCG comes with some builtin functional operations. Maybe is a monadic style wrapper for values that might be NULL. It provides a several operations for the wrapped value. * do(op) - runs op which is a function of one argument against the wrapped value if it is not null. Returns the result or NULL wrapped in another maybe. +* or(op) - runs op which is a function of no arguments if the wrapped value is null. Returns the result wrapped in another maybe. * is_null() - returns true if the wrapped value is null, false otherwise. * unwrap() - returns the wrapped value -* expect(msg) - returns the wrapped value if it is not null. Throws a compile error with the user provided message otherwise. \ No newline at end of file +* expect(msg) - returns the wrapped value if it is not null. Throws a compile error with the user provided message otherwise. + +``` +let maybe = import "std/functional.ucg".maybe; + +let result = maybe{val=NULL}.or(func () => "foo").do(func(v) => v + "bar"); +result == "foobar"; +``` \ No newline at end of file diff --git a/std/functional.ucg b/std/functional.ucg index 1f41622..c991895 100644 --- a/std/functional.ucg +++ b/std/functional.ucg @@ -3,6 +3,9 @@ // // * do - runs a user provided function of one argument on the value. // Returns a maybe wrapped result. +// +// * or - runs a user provided function of no arguments if the value is NULL. +// Returns a maybe wrapped result. // // * is_null - a function with no arguments that returns true if the value is // NULL and false if it is not. @@ -12,13 +15,17 @@ // * expect - Throws a compile error if the value is NULL. let maybe = module{ val = NULL, -} => ({do=do, is_null=is_null, unwrap=unwrap, expect=expect}) { +} => ({do=do, is_null=is_null, or=or, unwrap=unwrap, expect=expect}) { let maybe = import "std/functional.ucg".maybe; let do = func (op) => select (mod.val != NULL), maybe{val=NULL}, { true = maybe{val=op(mod.val)}, }; + let or = func (op) => select (mod.val == NULL), maybe{val=mod.val}, { + true = maybe{val=op()}, + }; + let is_null = func() => mod.val == NULL; let unwrap = func() => mod.val; diff --git a/std/tests/functional_test.ucg b/std/tests/functional_test.ucg index 8aeaec4..b529a77 100644 --- a/std/tests/functional_test.ucg +++ b/std/tests/functional_test.ucg @@ -18,6 +18,16 @@ assert t.ok{ desc = "maybe is still null after an operation", }; +assert t.equal{ + left = f.maybe{val=NULL}.or(func() => "foo").unwrap(), + right = "foo", +}; + +assert t.equal{ + left = f.maybe{val="bar"}.or(func() => "foo").unwrap(), + right = "bar", +}; + assert t.equal{ left = f.maybe{val={}}.do(op).unwrap(), right = {foo="bar"},