Skip to content

Commit

Permalink
more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
xrstf committed Nov 19, 2023
1 parent 692883a commit c947d0b
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 15 deletions.
15 changes: 15 additions & 0 deletions docs/functions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Otto Functions

Otto ships with a set of built-in functions. When embedding Otto, this set can
be extended or overwritten as desired to inject custom functions.

## Core

* [`default`](core-default.md) returns a fallback if the given value is
empty-ish.
* [`do`](core-do.md) evaluates expressions in sequence, sharing a context
between them.
* [`empty?`](core-empty.md) decides whether a given value is effectively empty
(for example `0` or `""`).
* [`if`](core-if.md) forms conditions.
* [`try`](core-try.md) returns a fallback value if an expression errors out.
36 changes: 36 additions & 0 deletions docs/functions/core-default.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# default

`default` is used to apply default values, especially when reading data from
user-defined inputs. Because of this, `default` uses a loose definition when
determining emptyness by using the `empty?` function internally. This means
values like `0` or `""` are considered empty.

`default` is similar to `try`, but only returns the fallback value if the value
is empty-ish. If an error occurs, `default` does not fall back to the fallback
value, but returns the error instead.

`default` is a shortcut to writing `(if (empty? expr-a) expr-b expr-a)`

## Examples

* `(default "" "fallback")` -> `"fallback"`
* `(default "set" "fallback")` -> `"set"`
* `(default (+ "invalid") "fallback")` -> error

## Forms

### `(default candidate fallback)`

* `candidate` is an arbitrary expression.
* `fallback` is an arbitrary expression.

`default` evaluates the candidate expression and returns the evaluated fallback
value if the returned candidate value is empty-ish. If the candidate expression
returns an error, the error is returned and the fallback expressions is not
evaluated.

## Context

`default` executes candidate and fallback in their own scopes, so variables from
either expression are not visible in the other and neither leak outside of
`default`.
30 changes: 30 additions & 0 deletions docs/functions/core-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# try

`try` is used to catch errors in expressions. It will evaluate an expression and
return its return value, unless the expression errors out, then a fallback value
is returned.

`try` is similar to `default`, but only returns the fallback value if an error
occurs, compared to `default` which tests for empty-ishness.

## Examples

* `(try (+ 1 2) "fallback")` -> `3` (no error occured in `+`)
* `(try (+ 1 "invalid") "fallback")` -> `"fallback"`
* `(try (+ 1 "invalid") (+ "also invalid"))` -> error

## Forms

### `(try candidate fallback)`

* `candidate` is an arbitrary expression.
* `fallback` is an arbitrary expression.

`try` evaluates the candidate expression and returns its return value upon
success. However when the candidate return an error, the fallback expression is
evaluated and its return value (or error) are returned.

## Context

`try` executes candidate and fallback in their own scopes, so variables from
either expression are not visible in the other and neither leak outside of `try`.
20 changes: 5 additions & 15 deletions pkg/eval/builtin/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,22 +312,12 @@ func isEmptyFunction(ctx types.Context, args []ast.Expression) (any, error) {
return nil, err
}

switch asserted := result.(type) {
case ast.Bool:
return bool(asserted) == false, nil
case ast.Number:
return asserted.ToFloat() == 0, nil
case ast.String:
return len(string(asserted)) == 0, nil
case ast.Null:
return true, nil
case ast.Vector:
return len(asserted.Data) == 0, nil
case ast.Object:
return len(asserted.Data) == 0, nil
default:
return nil, fmt.Errorf("unexpected argument %v (%T)", result, result)
empty, err := coalescing.IsEmpty(result)
if err != nil {
return nil, err
}

return ast.Bool(empty), nil
}

// (range VECTOR [item] expr+)
Expand Down

0 comments on commit c947d0b

Please sign in to comment.