FEATURE: Add an or operation on the maybe module type.

This commit is contained in:
Jeremy Wall 2019-02-28 20:59:17 -06:00
parent 04d7e06170
commit b4497d88e9
3 changed files with 27 additions and 2 deletions

View File

@ -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.
```
let maybe = import "std/functional.ucg".maybe;
let result = maybe{val=NULL}.or(func () => "foo").do(func(v) => v + "bar");
result == "foobar";
```

View File

@ -4,6 +4,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;

View File

@ -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"},