---
title: Functions
---

# Functions

This is complete list of all functions available to [Ripsaw](./language.md) scripts.

## Array functions


### `append`

Appends each item in the `items` array to the end of the `value` array.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The initial array. | | yes|
| items | any | The items to append. | | yes|

Append to an array:

```ripsaw
append([1, 2], [3, 4])

# returns [1,2,3,4]
```

### `chunks`

Chunks `value` into slices of length `chunk_size` bytes.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The array of bytes to split. | | yes|
| chunk_size | integer | The desired length of each chunk in bytes. This may be constrained by the host platform architecture. | | yes|

Split a string into chunks:

```ripsaw
chunks("abcdefgh", 4)

# returns ["abcd","efgh"]
```


Chunks do not respect unicode code point boundaries:

```ripsaw
chunks("ab你好", 4)

# returns ["ab�","�好"]
```

### `pop`

Removes the last item from the `value` array.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The target array. | | yes|

Pop an item from an array:

```ripsaw
pop([1, 2, 3])

# returns [1,2]
```

### `push`

Adds the `item` to the end of the `value` array.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The target array. | | yes|
| item | any | The item to push. | | yes|

Push an item onto an array:

```ripsaw
push([1, 2], 3)

# returns [1,2,3]
```


Empty array:

```ripsaw
push([], "bar")

# returns ["bar"]
```

### `zip`

Iterate over several arrays in parallel, producing a new array containing arrays of items from each source.
The resulting array will be as long as the shortest input array, with all the remaining elements dropped.
This function is modeled from the `zip` function [in Python](https://docs.python.org/3/library/functions.html#zip),
but similar methods can be found in [Ruby](https://docs.ruby-lang.org/en/master/Array.html#method-i-zip)
and [Rust](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.zip).

If a single parameter is given, it must contain an array of all the input arrays.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| array_0 | array | The first array of elements, or the array of input arrays if no other parameter is present. | | yes|
| array_1 | array | The second array of elements. If not present, the first parameter contains all the arrays. | | |

Merge two arrays:

```ripsaw
zip([1, 2, 3], [4, 5, 6, 7])

# returns [[1,4],[2,5],[3,6]]
```


Merge three arrays:

```ripsaw
zip([[1, 2], [3, 4], [5, 6]])

# returns [[1,3,5],[2,4,6]]
```


Merge an array of three arrays into an array of 3-tuples:

```ripsaw
zip([["a", "b", "c"], [1, null, true], [4, 5, 6]])

# returns [["a",1,4],["b",null,5],["c",true,6]]
```


Merge two array parameters:

```ripsaw
zip([1, 2, 3, 4], [5, 6, 7])

# returns [[1,5],[2,6],[3,7]]
```

## Debug functions

### `assert`

Checks that a condition is true, otherwise [aborting](./language.md#abort) the
script and discarding all results. The `assert()` function is
[fallible](./language.md#function-call), meaning that
[error handling](./errors.md#error-handling) is required for use.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| condition | boolean | condition to enforce | | yes|
| message   | string  | an optional custom error message | assertion failed | |

!!! warning
    The `assert()` function should only be used when you want to terminate the script upon failure.

validation with message:

```ripsaw
assert!(2 == 2, "two must be two")

# returns true
```

```ripsaw
thing = "y"
assert!(thing == "x", "thing must be x!")

# raises:
# function call error for "assert" at (0:41): thing must be x!
```

without a message:

```ripsaw
thing = "y"
assert!(thing == "x")

# raises:
# function call error for "assert" at (0:21): assertion failed
```

## Enumeration functions

### `all`

Tests each element in a collection, returning true only if the closure returned
true for all elements.

The function uses the "function closure syntax" to allow reading
the key/value or index/value combination for each item in the
collection.

The same scoping rules apply to closure blocks as they do for
regular blocks. This means that any variable defined in parent scopes
is accessible, and mutations to those variables are preserved,
but any new variables instantiated in the closure block are
unavailable outside of the block.

See the examples below to learn about the closure syntax.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | The object or array to iterate. | | | yes|

Find out if all elements are even:

```ripsaw
all([2, 4, 6]) -> |_index, num| {
  mod(num, 2) == 0
}

# returns true
```

```ripsaw
all({"a": 2, "b": 3}) -> |_key, num| {
  mod(num, 2) == 0
}

# returns false
```

### `any`

Tests each element in a collection until the closure returns true for any element.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | The object or array to iterate. | | | yes|

Find out if any element is six:

```ripsaw
any([2, 4, 6]) -> |_i, num| {
  num == 6
}

# returns true
```

```ripsaw
any({"a": 2, "b": 3}) -> |_key, num| {
  num == 6
}

# returns false
```

### `compact`

Compacts the `value` by removing empty values, where empty values are defined using the available parameters.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The object or array to compact. | | yes|
| recursive | boolean | Whether the compaction be recursive. | true| |
| null | boolean | Whether null should be treated as an empty value. | true| |
| string | boolean | Whether an empty string should be treated as an empty value. | true| |
| object | boolean | Whether an empty object should be treated as an empty value. | true| |
| array | boolean | Whether an empty array should be treated as an empty value. | true| |
| nullish | boolean | Tests whether the value is "nullish" as defined by the [`is_nullish`](#is_nullish) function. | false| |

Compact an object with default parameters:

```ripsaw
compact({"field1": 1, "field2": "", "field3": [], "field4": null})

# returns {"field1":1}
```


Compact an array with default parameters:

```ripsaw
compact(["foo", "bar", "", null, [], "buzz"])

# returns ["foo","bar","buzz"]
```


Compact an array using nullish:

```ripsaw
compact(["-", "   ", "\n", null, true], nullish: true)

# returns [true]
```


Compact a complex object with default parameters:

```ripsaw
compact({ "a": {}, "b": null, "c": [null], "d": "", "e": "-", "f": true })

# returns {"e":"-","f":true}
```


Compact a complex object using null: false:

```ripsaw
compact({ "a": {}, "b": null, "c": [null], "d": "", "e": "-", "f": true }, null: false)

# returns {"b":null,"c":[null],"e":"-","f":true}
```

### `filter`

Filter elements from a collection.

This function currently *does not* support recursive iteration.

The function uses the function closure syntax to allow reading
the key-value or index-value combination for each item in the
collection.

The same scoping rules apply to closure blocks as they do for
regular blocks. This means that any variable defined in parent scopes
is accessible, and mutations to those variables are preserved,
but any new variables instantiated in the closure block are
unavailable outside of the block.

See the examples below to learn about the closure syntax.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The array or object to filter. | | yes|

Filter elements:

```ripsaw
. = { "tags": ["foo", "bar", "foo", "baz"] }
filter(array(.tags)) -> |_index, value| {
    value != "foo"
}


# returns ["bar","baz"]
```


Filter object:

```ripsaw
filter({ "a": 1, "b": 2 }) -> |key, _value| { key == "a" }

# returns {"a":1}
```


Filter array:

```ripsaw
filter([1, 2]) -> |_index, value| { value < 2 }

# returns [1]
```

### `flatten`

Flattens the `value` into a single-level representation.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The array or object to flatten. | | yes|
| separator | string | The separator to join nested keys | .| |
| except | array of strings | An array of key names to exclude from flattening at any depth. | []| |

Flatten array:

```ripsaw
flatten([1, [2, 3, 4], [5, [6, 7], 8], 9])

# returns [1,2,3,4,5,6,7,8,9]
```


Flatten object:

```ripsaw
flatten({
    "parent1": {
        "child1": 1,
        "child2": 2
    },
    "parent2": {
        "child3": 3
    }
})


# returns {"parent1.child1":1,"parent1.child2":2,"parent2.child3":3}
```


Flatten object with custom separator:

```ripsaw
flatten({ "foo": { "bar": true }}, "_")

# returns {"foo_bar":true}
```


Flatten object with except:

```ripsaw
flatten({ "parent": { "child": 1 }, "keep": { "nested": 2 } }, except: ["keep"])

# returns {"keep":{"nested":2},"parent.child":1}
```

### `for_each`

Iterate over a collection.

This function currently *does not* support recursive iteration.

The function uses the "function closure syntax" to allow reading
the key/value or index/value combination for each item in the
collection.

The same scoping rules apply to closure blocks as they do for
regular blocks. This means that any variable defined in parent scopes
is accessible, and mutations to those variables are preserved,
but any new variables instantiated in the closure block are
unavailable outside of the block.

See the examples below to learn about the closure syntax.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The array or object to iterate. | | yes|

Tally elements:

```ripsaw
.tags = ["foo", "bar", "foo", "baz"]
tally = {}
for_each(array(.tags)) -> |_index, value| {
    count = int(get!(tally, [value])) ?? 0
    tally = set!(tally, [value], count + 1)
}
tally


# returns {"bar":1,"baz":1,"foo":2}
```


Iterate over an object:

```ripsaw
count = 0
for_each({ "a": 1, "b": 2 }) -> |_key, value| {
    count = count + value
}
count


# returns 3
```


Iterate over an array:

```ripsaw
count = 0
for_each([1, 2, 3]) -> |index, value| {
    count = count + index + value
}
count


# returns 9
```

### `includes`

Determines whether the `value` array includes the specified `item`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The array. | | yes|
| item | any | The item to check. | | yes|

Array includes:

```ripsaw
includes(["apple", "orange", "banana"], "banana")

# returns true
```


Includes boolean:

```ripsaw
includes([1, true], true)

# returns true
```


Doesn't include:

```ripsaw
includes(["foo", "bar"], "baz")


```

### `keys`

Returns the keys from the object passed into the function.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | object | The object to extract keys from. | | yes|

Get keys from the object:

```ripsaw
keys({
    "key1": "val1",
    "key2": "val2"
})


# returns ["key1","key2"]
```

### `length`

Returns the length of the `value`.

* If `value` is an array, returns the number of elements.
* If `value` is an object, returns the number of top-level keys.
* If `value` is a string, returns the number of bytes in the string. If
  you want the number of characters, see `strlen`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The array or object. | | yes|

Length (object):

```ripsaw
length({
    "portland": "Trail Blazers",
    "seattle": "Supersonics"
})


# returns 2
```


Length (nested object):

```ripsaw
length({
    "home": {
        "city":  "Portland",
        "state": "Oregon"
    },
    "name": "Trail Blazers",
    "mascot": {
        "name": "Blaze the Trail Cat"
    }
})


# returns 3
```


Length (array):

```ripsaw
length(["Trail Blazers", "Supersonics", "Grizzlies"])

# returns 3
```


Length (string):

```ripsaw
length("The Planet of the Apes Musical")

# returns 30
```

### `map`

Transform each of the elements of an array.

Iterate over each element in an array, applying a transformation from a closure.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | object | The object to iterate. | | yes|

Upcase elements:

```ripsaw
map(["foo", "bar", "baz"]) -> |_index, item| { upcase(item) }

# returns ["FOO", "BAR", "BAZ"]
```

Multiply:

```ripsaw
map([2, 3, 4]) -> |_index, item| { item * 2 }

# returns [4, 6, 8]
```


### `map_keys`

Map the keys within an object.

If `recursive` is enabled, the function iterates into nested
objects, using the following rules:

1. Iteration starts at the root.
2. For every nested object type:
   - First return the key of the object type itself.
   - Then recurse into the object, and loop back to item (1)
     in this list.
   - Any mutation done on a nested object *before* recursing into
     it, are preserved.
3. For every nested array type:
   - First return the key of the array type itself.
   - Then find all objects within the array, and apply item (2)
     to each individual object.

The above rules mean that `map_keys` with
`recursive` enabled finds *all* keys in the target,
regardless of whether nested objects are nested inside arrays.

The function uses the function closure syntax to allow reading
the key for each item in the object.

The same scoping rules apply to closure blocks as they do for
regular blocks. This means that any variable defined in parent scopes
is accessible, and mutations to those variables are preserved,
but any new variables instantiated in the closure block are
unavailable outside of the block.

See the examples below to learn about the closure syntax.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | object | The object to iterate. | | yes|
| recursive | boolean | Whether to recursively iterate the collection. | false| |

Upcase keys:

```ripsaw
. = {
    "foo": "foo",
    "bar": "bar",
    "baz": {"nested key": "val"}
}
map_keys(.) -> |key| { upcase(key) }


# returns {"FOO":"foo","BAR":"bar","BAZ":{"nested key":"val"}}
```


De-dot keys:

```ripsaw
. = {
    "labels": {
        "app.kubernetes.io/name": "mysql"
    }
}
map_keys(., recursive: true) -> |key| { replace(key, ".", "_") }


# returns {"labels":{"app_kubernetes_io/name":"mysql"}}
```


Recursively map object keys:

```ripsaw
val = {
    "a": 1,
    "b": [{ "c": 2 }, { "d": 3 }],
    "e": { "f": 4 }
}
map_keys(val, recursive: true) -> |key| { upcase(key) }


# returns {"A":1,"B":[{"C":2},{"D":3}],"E":{"F":4}}
```

### `map_values`

Map the values within a collection.

If `recursive` is enabled, the function iterates into nested
collections, using the following rules:

1. Iteration starts at the root.
2. For every nested collection type:
   - First return the collection type itself.
   - Then recurse into the collection, and loop back to item (1)
     in the list
   - Any mutation done on a collection *before* recursing into it,
     are preserved.

The function uses the function closure syntax to allow mutating
the value for each item in the collection.

The same scoping rules apply to closure blocks as they do for
regular blocks, meaning, any variable defined in parent scopes
are accessible, and mutations to those variables are preserved,
but any new variables instantiated in the closure block are
unavailable outside of the block.

Check out the examples below to learn about the closure syntax.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The object or array to iterate. | | yes|
| recursive | boolean | Whether to recursively iterate the collection. | false| |

Upcase values:

```ripsaw
. = {
    "foo": "foo",
    "bar": "bar"
}
map_values(.) -> |value| { upcase(value) }


# returns {"foo":"FOO","bar":"BAR"}
```


Recursively map object values:

```ripsaw
val = {
    "a": 1,
    "b": [{ "c": 2 }, { "d": 3 }],
    "e": { "f": 4 }
}
map_values(val, recursive: true) -> |value| {
    if is_integer(value) { int!(value) + 1 } else { value }
}


# returns {"a":2,"b":[{"c":3},{"d":4}],"e":{"f":5}}
```

### `match_array`

Determines whether the elements in the `value` array matches the `pattern`. By default, it checks that at least one element matches, but can be set to determine if all the elements match.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The array. | | yes|
| pattern | regex | The regular expression pattern to match against. | | yes|
| all | boolean | Whether to match on all elements of `value`. | false| |

Match at least one element:

```ripsaw
match_array(["foobar", "bazqux"], r'foo')

# returns true
```


Match all elements:

```ripsaw
match_array(["foo", "foobar", "barfoo"], r'foo', all: true)

# returns true
```


No matches:

```ripsaw
match_array(["bazqux", "xyz"], r'foo')


```


Not all elements match:

```ripsaw
match_array(["foo", "foobar", "baz"], r'foo', all: true)


```

### `strlen`

Returns the number of UTF-8 characters in `value`. This differs from
`length` which counts the number of bytes of a string.

!!! note ""
    This is the count of [Unicode scalar values](https://www.unicode.org/glossary/#unicode_scalar_value) which can sometimes differ from [Unicode code points](https://www.unicode.org/glossary/#code_point).

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string. | | yes|

Count Unicode scalar values:

```ripsaw
strlen("ñandú")

# returns 5
```

### `tally`

Counts the occurrences of each string value in the provided array and returns an object with the counts.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The array of strings to count occurrences for. | | yes|

tally:

```ripsaw
tally!(["foo", "bar", "foo", "baz"])

# returns {"foo":2,"bar":1,"baz":1}
```

### `tally_value`

Counts the number of times a specific value appears in the provided array.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| array | array | The array to search through. | | yes|
| value | integer | The value to count occurrences of in the array. | | yes|

count matching values:

```ripsaw
tally_value(["foo", "bar", "foo", "baz"], "foo")

# returns 2
```

### `unflatten`

Unflattens the `value` into a nested representation.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The array or object to unflatten. | | yes|
| separator | string | The separator to split flattened keys. | .| |
| recursive | boolean | Whether to recursively unflatten the object values. | true| |

Unflatten:

```ripsaw
unflatten({
    "foo.bar.baz": true,
    "foo.bar.qux": false,
    "foo.quux": 42
})


# returns {"foo":{"bar":{"baz":true,"qux":false},"quux":42}}
```


Unflatten recursively:

```ripsaw
unflatten({
    "flattened.parent": {
        "foo.bar": true,
        "foo.baz": false
    }
})


# returns {"flattened":{"parent":{"foo":{"bar":true,"baz":false}}}}
```


Unflatten non-recursively:

```ripsaw
unflatten({
    "flattened.parent": {
        "foo.bar": true,
        "foo.baz": false
    }
}, recursive: false)


# returns {"flattened":{"parent":{"foo.bar":true,"foo.baz":false}}}
```


Ignore inconsistent keys values:

```ripsaw
unflatten({
    "a": 3,
    "a.b": 2,
    "a.c": 4
})


# returns {"a":{"b":2,"c":4}}
```


Unflatten with custom separator:

```ripsaw
unflatten({ "foo_bar": true }, "_")

# returns {"foo":{"bar":true}}
```

### `unique`

Returns the unique values for an array.

The first occurrence of each element is kept.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array | The array to return unique elements from. | | yes|

Unique:

```ripsaw
unique(["foo", "bar", "foo", "baz"])

# returns ["foo","bar","baz"]
```

### `values`

Returns the values from the object passed into the function.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | object | The object to extract values from. | | yes|

Get values from the object:

```ripsaw
values({"key1": "val1", "key2": "val2"})

# returns ["val1","val2"]
```


Get values from a complex object:

```ripsaw
values({"key1": "val1", "key2": [1, 2, 3], "key3": {"foo": "bar"}})

# returns ["val1",[1,2,3],{"foo":"bar"}]
```

## Issue and Crash functions

!!! note ""
    Create a workflow using the [Issue / Crash condition](../workflow-steps.md#issue-crash) to use these functions.

Issue functions have a [`Report`](./structures.md#report) object as the program input.

### `add_field`

Emit metrics which will be used as input to [Plot Charts](../actions.md#plot-charts). No metrics will be added for a Report when [`abort`](./language.md#abort) is called.

| Parameter | Type   | Description           | Default | Required |
|-----------|--------|-----------------------|---------|----------|
| name      | string | name of metric to add |         | yes      |
| value     | string | metric value          |         | yes      |

Using [feature flags](../../../sdk/features/feature-flags.md):

```ripsaw
my_flags = ["test_a", "test_b"]

matching = filter(.feature_flags) -> |_index, flag| {
  contains(my_flags, flag.name)
}

if length(matching) == 0 {
  abort # discard metrics for this report
}

for_each(matching) -> |_index, flag| {
  add_field(flag.name, flag.value)
}
```

Using [custom fields](../../../sdk/features/fields.md#custom-fields):

```ripsaw
# find a particular custom field
value = .fields.prod_category
if is_string(value) {
  add_field("category", to_string(value))
} else {
  abort # discard metrics for this report
}
```

```ripsaw
my_fields = ["prod_category", "option_split"]

for_each(my_fields) -> |_index, key| {
  value, err = get(.fields, [key])
  if err == null && is_string(value) {
    add_field(key, value)
  }
}
```

Based on the [Report Type](./structures.md#reporttype) and [Error](./structures.md#error) reason:

```ripsaw
if .type == "AppNotResponding" {
  reason, err = get(.errors, [0, "reason"])
  if err == null && is_string(reason)
    && contains(reason, "Input dispatching timed out") {
    add_field("ANR", "slow UI")
  } else {
    add_field("ANR", "other")
  }
}
```

From the [Frames](./structures.md#frame) the stack trace of a Report:

```ripsaw
# find if any frame in any error matches an exact symbol name
has_important_thing = any(.errors) -> |_i, error| {
  any(error.stack_trace) -> |_j, frame| {
    frame.symbolicated_name == "examplelib.my_function"
  }
}

add_field("important", to_string(has_important_thing))
```

```ripsaw
# find all frames containing a particular module in the symbol name
matching_frames = flatten(map(.errors) -> |_i, error| {
  filter(error.stack_trace) -> |_j, frame| {
    is_string(frame.symbolicated_name)
      && contains(frame.symbolicated_name, "MyModule")
  }
})

if length(matching_frames) > 0 {
  add_field("MyModule Team", matching_frames[0].symbolicated_name)
} else {
  abort # discard metric results for this report
}
```

## Path functions


### `del`

Removes the field specified by the static `path` from the target.

For dynamic path deletion, see the `remove` function.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| target | path | The path of the field to delete | | yes|
| compact | boolean | After deletion, if `compact` is `true` and there is an empty object or array left,
the empty object or array is also removed, cascading up to the root. This only
applies to the path being deleted, and any parent paths. | false| |

Delete a field:

```ripsaw
. = { "foo": "bar" }
del(.foo)


# returns bar
```


Rename a field:

```ripsaw
. = { "old": "foo" }
.new = del(.old)
.


# returns {"new":"foo"}
```


Returns null for unknown field:

```ripsaw
del({"foo": "bar"}.baz)


```


External target:

```ripsaw
. = { "foo": true, "bar": 10 }
del(.foo)
.


# returns {"bar":10}
```


Delete field from variable:

```ripsaw
var = { "foo": true, "bar": 10 }
del(var.foo)
var


# returns {"bar":10}
```


Delete object field:

```ripsaw
var = { "foo": {"nested": true}, "bar": 10 }
del(var.foo.nested, false)
var


# returns {"foo":{},"bar":10}
```


Compact object field:

```ripsaw
var = { "foo": {"nested": true}, "bar": 10 }
del(var.foo.nested, true)
var


# returns {"bar":10}
```

### `exists`

Checks whether the `path` exists for the target.

This function distinguishes between a missing path
and a path with a `null` value. A regular path lookup,
such as `.foo`, cannot distinguish between the two cases
since it always returns `null` if the path doesn't exist.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| field | path | The path of the field to check. | | yes|

Exists (field):

```ripsaw
. = { "field": 1 }
exists(.field)


# returns true
```


Exists (array element):

```ripsaw
. = { "array": [1, 2, 3] }
exists(.array[2])


# returns true
```


Does not exist (field):

```ripsaw
exists({ "foo": "bar"}.baz)


```

### `get`

Dynamically get the value of a given path.

If you know the path you want to look up, use
static paths such as `.foo.bar[1]` to get the value of that
path. However, if you do not know the path names,
use the dynamic `get` function to get the requested value.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The object or array to query. | | yes|
| path | path | An array of path segments to look for the value. | | yes|

Single-segment top-level field:

```ripsaw
get!(value: {"foo": "bar"}, path: ["foo"])

# returns bar
```


Returns null for unknown field:

```ripsaw
get!(value: {"foo": "bar"}, path: ["baz"])


```


Multi-segment nested field:

```ripsaw
get!(value: {"foo": { "bar": true }}, path: ["foo", "bar"])

# returns true
```


Array indexing:

```ripsaw
get!(value: [92, 42], path: [0])

# returns 92
```


Array indexing (negative):

```ripsaw
get!(value: ["foo", "bar", "baz"], path: [-2])

# returns bar
```


Nested indexing:

```ripsaw
get!(value: {"foo": { "bar": [92, 42] }}, path: ["foo", "bar", 1])

# returns 42
```


External target:

```ripsaw
get!(value: ., path: ["foo"])

# returns true
```


Variable:

```ripsaw
var = { "foo": true }
get!(value: var, path: ["foo"])


# returns true
```


Missing index:

```ripsaw
get!(value: {"foo": { "bar": [92, 42] }}, path: ["foo", "bar", 1, -1])


```


Invalid indexing:

```ripsaw
get!(value: [42], path: ["foo"])


```


Invalid segment type:

```ripsaw
get!(value: {"foo": { "bar": [92, 42] }}, path: ["foo", true])


```

### `remove`

Dynamically remove the value for a given path.

If you know the path you want to remove, use
the `del` function and static paths such as `del(.foo.bar[1])`
to remove the value at that path. The `del` function returns the
deleted value, and is more performant than `remove`.
However, if you do not know the path names, use the dynamic
`remove` function to remove the value at the provided path.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The object or array to remove data from. | | yes|
| path | path | An array of path segments to remove the value from. | | yes|
| compact | boolean | After deletion, if `compact` is `true`, any empty objects or
arrays left are also removed. | false| |

Single-segment top-level field:

```ripsaw
remove!(value: { "foo": "bar" }, path: ["foo"])

# returns {}
```


Remove unknown field:

```ripsaw
remove!(value: {"foo": "bar"}, path: ["baz"])

# returns {"foo":"bar"}
```


Multi-segment nested field:

```ripsaw
remove!(value: { "foo": { "bar": "baz" } }, path: ["foo", "bar"])

# returns {"foo":{}}
```


Array indexing:

```ripsaw
remove!(value: ["foo", "bar", "baz"], path: [-2])

# returns ["foo","baz"]
```


Compaction:

```ripsaw
remove!(value: { "foo": { "bar": [42], "baz": true } }, path: ["foo", "bar", 0], compact: true)

# returns {"foo":{"baz":true}}
```


Compact object:

```ripsaw
remove!(value: {"foo": { "bar": true }}, path: ["foo", "bar"], compact: true)

# returns {}
```


Compact array:

```ripsaw
remove!(value: {"foo": [42], "bar": true }, path: ["foo", 0], compact: true)

# returns {"bar":true}
```


External target:

```ripsaw
remove!(value: ., path: ["foo"])

# returns {}
```


Variable:

```ripsaw
var = { "foo": true }
remove!(value: var, path: ["foo"])


# returns {}
```


Missing index:

```ripsaw
remove!(value: {"foo": { "bar": [92, 42] }}, path: ["foo", "bar", 1, -1])

# returns {"foo":{"bar":[92,42]}}
```


Invalid indexing:

```ripsaw
remove!(value: [42], path: ["foo"])

# returns [42]
```


Invalid segment type:

```ripsaw
remove!(value: {"foo": { "bar": [92, 42] }}, path: ["foo", true])


```

### `set`

Dynamically insert data into the path of a given object or array.

If you know the path you want to assign a value to,
use static path assignments such as `.foo.bar[1] = true` for
improved performance and readability. However, if you do not
know the path names, use the dynamic `set` function to
insert the data into the object or array.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The object or array to insert data into. | | yes|
| path | path | An array of path segments to insert the value into. | | yes|
| data | any | The data to be inserted. | | yes|

Single-segment top-level field:

```ripsaw
set!(value: { "foo": "bar" }, path: ["foo"], data: "baz")

# returns {"foo":"baz"}
```


Multi-segment nested field:

```ripsaw
set!(value: { "foo": { "bar": "baz" } }, path: ["foo", "bar"], data: "qux")

# returns {"foo":{"bar":"qux"}}
```


Array:

```ripsaw
set!(value: ["foo", "bar", "baz"], path: [-2], data: 42)

# returns ["foo",42,"baz"]
```


Nested fields:

```ripsaw
set!(value: {}, path: ["foo", "bar"], data: "baz")

# returns {"foo":{"bar":"baz"}}
```


Nested indexing:

```ripsaw
set!(value: {"foo": { "bar": [] }}, path: ["foo", "bar", 1], data: "baz")

# returns {"foo":{"bar":[null,"baz"]}}
```


External target:

```ripsaw
set!(value: ., path: ["bar"], data: "baz")

# returns {"foo":true,"bar":"baz"}
```


Variable:

```ripsaw
var = { "foo": true }
set!(value: var, path: ["bar"], data: "baz")


# returns {"foo":true,"bar":"baz"}
```


Invalid indexing:

```ripsaw
set!(value: [], path: ["foo"], data: "baz")

# returns {"foo":"baz"}
```


Invalid segment type:

```ripsaw
set!({"foo": { "bar": [92, 42] }}, ["foo", true], "baz")


```


## Number functions

### `abs`

Computes the absolute value of `value`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | number | The number to calculate the absolute value. | | yes|

Computes the absolute value of an integer:

```ripsaw
abs(-42)

# returns 42
```


Computes the absolute value of a float:

```ripsaw
abs(-42.2)

# returns 42.2
```


Computes the absolute value of a positive integer:

```ripsaw
abs(10)

# returns 10
```

### `ceil`

Rounds the `value` up to the specified `precision`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | number | The number to round up. | | yes|
| precision | integer | The number of decimal places to round to. | 0| |

Round a number up (without precision):

```ripsaw
ceil(4.345)

# returns 5.0
```


Round a number up (with precision):

```ripsaw
ceil(4.345, precision: 2)

# returns 4.35
```


Round an integer up (noop):

```ripsaw
ceil(5)

# returns 5
```

### `floor`

Rounds the `value` down to the specified `precision`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | number | The number to round down. | | yes|
| precision | integer | The number of decimal places to round to. | 0| |

Round a number down (without precision):

```ripsaw
floor(9.8)

# returns 9.0
```


Round a number down (with precision):

```ripsaw
floor(4.345, precision: 2)

# returns 4.34
```

### `format_int`

Formats the integer `value` into a string representation using the given base/radix.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | number | The number to format. | | yes|
| base | integer | The base to format the number in. Must be between 2 and 36 (inclusive). | 10| |

Format as a hexadecimal integer:

```ripsaw
format_int!(42, 16)

# returns 2a
```


Format as a negative hexadecimal integer:

```ripsaw
format_int!(-42, 16)

# returns -2a
```


Format as a decimal integer (default base):

```ripsaw
format_int!(42)

# returns 42
```

### `format_number`

Formats the `value` into a string representation of the number.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | number | The number to format as a string. | | yes|
| scale | integer | The number of decimal places to display. | | |
| decimal_separator | string | The character to use between the whole and decimal parts of the number. | .| |
| grouping_separator | string | The character to use between each thousands part of the number. | | |

Format a number (3 decimals):

```ripsaw
format_number(1234567.89, 3, decimal_separator: ".", grouping_separator: ",")

# returns 1,234,567.890
```


Format a number with European-style separators:

```ripsaw
format_number(4672.4, decimal_separator: ",", grouping_separator: "_")

# returns 4_672,4
```


Format a number with a middle dot separator:

```ripsaw
format_number(4321.09, 3, decimal_separator: "·")

# returns 4321·090
```

### `mod`

Calculates the remainder of `value` divided by `modulus`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | integer | The value the `modulus` is applied to. | | yes|
| modulus | integer | The `modulus` value. | | yes|

Calculate the remainder of two integers:

```ripsaw
mod(5, 2)

# returns 1
```

### `round`

Rounds the `value` to the specified `precision`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | number | The number to round. | | yes|
| precision | integer | The number of decimal places to round to. | 0| |

Round a number (without precision):

```ripsaw
round(4.345)

# returns 4.0
```


Round a number (with precision):

```ripsaw
round(4.345, precision: 2)

# returns 4.35
```


Round up:

```ripsaw
round(5.5)

# returns 6.0
```


Round down:

```ripsaw
round(5.45)

# returns 5.0
```


## Object functions

### `from_entries`

Converts array of key/value objects into an object.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The array of key/value objects to convert. | | yes|

Manipulate empty array:

```ripsaw
from_entries([])

# returns {}
```


Manipulate array:

```ripsaw
from_entries([{ "key": "foo", "value": "bar" }])

# returns {"foo":"bar"}
```

### `merge`

Merges the `from` object into the `to` object.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| to | object | The object to merge into. | | yes|
| from | object | The object to merge from. | | yes|
| deep | boolean | A deep merge is performed if `true`, otherwise only top-level fields are merged. | false| |

Object merge (shallow):

```ripsaw
merge(
    {
        "parent1": {
            "child1": 1,
            "child2": 2
        },
        "parent2": {
            "child3": 3
        }
    },
    {
        "parent1": {
            "child2": 4,
            "child5": 5
        }
    }
)


# returns {"parent1":{"child2":4,"child5":5},"parent2":{"child3":3}}
```


Object merge (deep):

```ripsaw
merge(
    {
        "parent1": {
            "child1": 1,
            "child2": 2
        },
        "parent2": {
            "child3": 3
        }
    },
    {
        "parent1": {
            "child2": 4,
            "child5": 5
        }
    },
    deep: true
)


# returns {"parent1":{"child1":1,"child2":4,"child5":5},"parent2":{"child3":3}}
```

### `object_from_array`

Iterate over either one array of arrays or a pair of arrays and create an object out of all the key-value pairs contained in them.
With one array of arrays, any entries with no value use `null` instead.
Any keys that are `null` skip the  corresponding value.

If a single parameter is given, it must contain an array of all the input arrays.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| values | array | The first array of elements, or the array of input arrays if no other parameter is present. | | yes|
| keys | array | The second array of elements. If not present, the first parameter must contain all the arrays. | | |

Create an object from one array:

```ripsaw
object_from_array([["one", 1], [null, 2], ["two", 3]])

# returns {"one":1,"two":3}
```


Create an object from separate key and value arrays:

```ripsaw
object_from_array([1, 2, 3], keys: ["one", null, "two"])

# returns {"one":1,"two":3}
```


Create an object from a separate arrays of keys and values:

```ripsaw
object_from_array(values: [1, null, true], keys: ["a", "b", "c"])

# returns {"a":1,"b":null,"c":true}
```

### `to_entries`

Converts JSON objects or arrays into array of objects.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object | The object or array to manipulate. | | yes|

Manipulate empty object:

```ripsaw
to_entries({})

# returns []
```


Manipulate object:

```ripsaw
to_entries({ "foo": "bar"})

# returns [{"key":"foo","value":"bar"}]
```


Manipulate array:

```ripsaw
to_entries([1, 2])

# returns [{"key":0,"value":1},{"key":1,"value":2}]
```

### `unnest`

Unnest an array field from an object to create an array of objects using that field; keeping all other fields.

This is also referred to as `explode` in some languages.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| path | path | The path of the field to unnest. | | yes|

Unnest an array field:

```ripsaw
. = {"hostname": "localhost", "messages": ["message 1", "message 2"]}
. = unnest(.messages)


# returns [{"hostname":"localhost","messages":"message 1"},{"hostname":"localhost","messages":"message 2"}]
```


Unnest a nested array field:

```ripsaw
. = {"hostname": "localhost", "event": {"messages": ["message 1", "message 2"]}}
. = unnest(.event.messages)


# returns [{"hostname":"localhost","event":{"messages":"message 1"}},{"hostname":"localhost","event":{"messages":"message 2"}}]
```


## String functions

### `basename`

Returns the filename component of the given `path`. This is similar to the Unix `basename` command. If the path ends in a directory separator, the function returns the name of the directory.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The path from which to extract the basename. | | yes|

Extract basename from file path:

```ripsaw
basename!("/usr/local/bin/rustc")

# returns rustc
```


Extract basename from file path with extension:

```ripsaw
basename!("/home/user/file.txt")

# returns file.txt
```


Extract basename from directory path:

```ripsaw
basename!("/home/user/")

# returns user
```


Root directory has no basename:

```ripsaw
basename!("/")


```

### `camelcase`

Takes the `value` string, and turns it into camelCase. Optionally, you can pass in the existing case of the function, or else an attempt is made to determine the case automatically.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to convert to camelCase. | | yes|
| original_case | string | Optional hint on the original case type. Must be one of: kebab-case, camelCase, PascalCase, SCREAMING_SNAKE, snake_case | | |

camelCase a string without specifying original case:

```ripsaw
camelcase("input-string")

# returns inputString
```


camelcase a snake_case string:

```ripsaw
camelcase("foo_bar_baz", "snake_case")

# returns fooBarBaz
```


camelcase specifying the wrong original case (noop):

```ripsaw
camelcase("foo_bar_baz", "kebab-case")

# returns foo_bar_baz
```

### `contains`

Determines whether the `value` string contains the specified `substring`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The text to search. | | yes|
| substring | string | The substring to search for in `value`. | | yes|
| case_sensitive | boolean | Whether the match should be case sensitive. | true| |

String contains with default parameters (case sensitive):

```ripsaw
contains("banana", "AnA")


```


String contains (case insensitive):

```ripsaw
contains("banana", "AnA", case_sensitive: false)

# returns true
```

### `contains_all`

Determines whether the `value` string contains all the specified `substrings`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The text to search. | | yes|
| substrings | array | An array of substrings to search for in `value`. | | yes|
| case_sensitive | boolean | Whether the match should be case sensitive. | | |

String contains all with default parameters (case sensitive):

```ripsaw
contains_all("The NEEDLE in the Haystack", ["NEEDLE", "Haystack"])

# returns true
```


String doesn't contain all with default parameters (case sensitive):

```ripsaw
contains_all("The NEEDLE in the Haystack", ["needle", "Haystack"])


```


String contains all (case insensitive):

```ripsaw
contains_all("The NEEDLE in the HaYsTaCk", ["nEeDlE", "haystack"], case_sensitive: false)

# returns true
```

### `dirname`

Returns the directory component of the given `path`. This is similar to the Unix `dirname` command. The directory component is the path with the final component removed.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The path from which to extract the directory name. | | yes|

Extract dirname from file path:

```ripsaw
dirname!("/usr/local/bin/cargo")

# returns /usr/local/bin
```


Extract dirname from file path with extension:

```ripsaw
dirname!("/home/user/file.txt")

# returns /home/user
```


Extract dirname from directory path:

```ripsaw
dirname!("/home/user/")

# returns /home
```


Root directory dirname is itself:

```ripsaw
dirname!("/")

# returns /
```


Relative files have current directory as dirname:

```ripsaw
dirname!("file.txt")

# returns .
```

### `downcase`

Downcases the `value` string, where downcase is defined according to the Unicode Derived Core Property Lowercase.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to convert to lowercase. | | yes|

Downcase a string:

```ripsaw
downcase("Hello, World!")

# returns hello, world!
```


Downcase with number:

```ripsaw
downcase("FOO 2 BAR")

# returns foo 2 bar
```

### `ends_with`

Determines whether the `value` string ends with the specified `substring`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to search. | | yes|
| substring | string | The substring with which `value` must end. | | yes|
| case_sensitive | boolean | Whether the match should be case sensitive. | true| |

String ends with (case sensitive):

```ripsaw
ends_with("The Needle In The Haystack", "The Haystack")

# returns true
```


String ends with (case insensitive):

```ripsaw
ends_with("The Needle In The Haystack", "the haystack", case_sensitive: false)

# returns true
```


String ends with (case sensitive failure):

```ripsaw
ends_with("foobar", "R")


```

### `find`

Determines from left to right the start position of the first found element in `value` that matches `pattern`. Returns `-1` if not found.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to find the pattern in. | | yes|
| pattern | regex | The regular expression or string pattern to match against. | | yes|
| from | integer | Offset to start searching. | 0| |

Match text:

```ripsaw
find("foobar", "bar")

# returns 3
```


Match text at start:

```ripsaw
find("foobar", "foo")

# returns 0
```


Match regex:

```ripsaw
find("foobar", r'b.r')

# returns 3
```


No matches:

```ripsaw
find("foobar", "baz")


```


With an offset:

```ripsaw
find("foobarfoobarfoo", "bar", 4)

# returns 9
```

### `join`

Joins each string in the `value` array into a single string, with items optionally separated from one another by a `separator`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The array of strings to join together. | | yes|
| separator | string | The string separating each original element when joined. | | |

Join array (no separator):

```ripsaw
join!(["bring", "us", "together"])

# returns bringustogether
```


Join array (comma separator):

```ripsaw
join!(["sources", "transforms", "sinks"], separator: ", ")

# returns sources, transforms, sinks
```

### `kebabcase`

Takes the `value` string, and turns it into kebab-case. Optionally, you can pass in the existing case of the function, or else we will try to figure out the case automatically.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to convert to kebab-case. | | yes|
| original_case | string | Optional hint on the original case type. Must be one of: kebab-case, camelCase, PascalCase, SCREAMING_SNAKE, snake_case | | |

kebab-case a string without specifying original case:

```ripsaw
kebabcase("InputString")

# returns input-string
```


kebab-case a snake_case string:

```ripsaw
kebabcase("foo_bar_baz", "snake_case")

# returns foo-bar-baz
```


kebab-case specifying the wrong original case (noop):

```ripsaw
kebabcase("foo_bar_baz", "PascalCase")

# returns foo_bar_baz
```

### `match`

Determines whether the `value` matches the `pattern`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The value to match. | | yes|
| pattern | regex | The regular expression pattern to match against. | | yes|

Regex match on a string:

```ripsaw
match("I'm a little teapot", r'teapot')

# returns true
```


String does not match the regular expression:

```ripsaw
match("I'm a little teapot", r'.*balloon')


```

### `match_any`

Determines whether `value` matches any of the given `patterns`. All patterns are checked in a single pass over the target string, giving this function a potential performance advantage over the multiple calls in the `match` function.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The value to match. | | yes|
| patterns | array of regexes | The array of regular expression patterns to match against. | | yes|

Regex match on a string:

```ripsaw
match_any("I'm a little teapot", [r'frying pan', r'teapot'])

# returns true
```


No match:

```ripsaw
match_any("My name is John Doe", patterns: [r'\d+', r'Jane'])


```

### `parse_float`

Parses the string `value` representing a floating point number in base 10 to a float.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to parse. | | yes|

Parse negative integer:

```ripsaw
parse_float!("-42")

# returns -42.0
```


Parse float:

```ripsaw
parse_float!("42.38")

# returns 42.38
```


Scientific notation:

```ripsaw
parse_float!("2.5e3")

# returns 2500.0
```

### `pascalcase`

Takes the `value` string, and turns it into PascalCase. Optionally, you can pass in the existing case of the function, or else we will try to figure out the case automatically.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to convert to PascalCase. | | yes|
| original_case | string | Optional hint on the original case type. Must be one of: kebab-case, camelCase, PascalCase, SCREAMING_SNAKE, snake_case | | |

PascalCase a string without specifying original case:

```ripsaw
pascalcase("input-string")

# returns InputString
```


PascalCase a snake_case string:

```ripsaw
pascalcase("foo_bar_baz", "snake_case")

# returns FooBarBaz
```


PascalCase specifying the wrong original case (only capitalizes):

```ripsaw
pascalcase("foo_bar_baz", "kebab-case")

# returns Foo_bar_baz
```

### `replace`

Replaces all matching instances of `pattern` in `value`.

The `pattern` argument accepts regular expression capture groups.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The original string. | | yes|
| pattern | regex | Replace all matches of this pattern. Can be a static string or a regular expression. | | yes|
| with | string | The string that the matches are replaced with. | | yes|
| count | integer | The maximum number of replacements to perform. `-1` means replace all matches. | -1| |

Replace literal text:

```ripsaw
replace("Apples and Bananas", "and", "not")

# returns Apples not Bananas
```


Replace using regular expression:

```ripsaw
replace("Apples and Bananas", r'(?i)bananas', "Pineapples")

# returns Apples and Pineapples
```


Replace first instance:

```ripsaw
replace("Bananas and Bananas", "Bananas", "Pineapples", count: 1)

# returns Pineapples and Bananas
```


Replace with capture groups:

```ripsaw
replace("foo123bar", r'foo(?P<num>\d+)bar', "$num")


# returns 123
```


Replace all:

```ripsaw
replace("foobar", "o", "i")

# returns fiibar
```

### `replace_with`

Replaces all matching instances of `pattern` using a closure.

The `pattern` argument accepts a regular expression that can use capture groups.

The function uses the function closure syntax to compute the replacement values.

The closure takes a single parameter, which is an array, where the first item is always
present and contains the entire string that matched `pattern`. The items from index one on
contain the capture groups of the corresponding index. If a capture group is optional, the
value may be null if it didn't match.

The value returned by the closure must be a string and will replace the section of
the input that was matched.

This returns a new string with the replacements, the original string is not mutated.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The original string. | | yes|
| pattern | regex | Replace all matches of this pattern. Must be a regular expression. | | yes|
| count | integer | The maximum number of replacements to perform. `-1` means replace all matches. | -1| |

Capitalize words:

```ripsaw
replace_with("apples and bananas", r'\b(\w)(\w*)') -> |match| {
    upcase!(match.captures[0]) + string!(match.captures[1])
}


# returns Apples And Bananas
```


Replace with hash:

```ripsaw
replace_with("email from test@example.com", r'\w+@example.com') -> |match| {
    "[REDACTED]"
}


# returns email from [REDACTED]
```


Replace first instance:

```ripsaw
replace_with("Apples and Apples", r'(?i)apples|cones', count: 1) -> |match| {
    "Pine" + downcase(match.string)
}


# returns Pineapples and Apples
```


Named capture group:

```ripsaw
replace_with("level=error A message", r'level=(?P<level>\w+)') -> |match| {
    lvl = upcase!(match.level)
    "[{{lvl}}]"
}


# returns [ERROR] A message
```


Replace with processed capture group:

```ripsaw
replace_with(s'Got message: {"msg": "b"}', r'message: (\{.*\})') -> |m| {
    to_string!(m.captures[0])
}


# returns Got {"msg": "b"}
```


Replace with optional capture group:

```ripsaw
replace_with("bar of chocolate and bar of gold", r'bar( of gold)?') -> |m| {
    if m.captures[0] == null { "pile" } else { "money" }
}


# returns pile of chocolate and money
```

### `screamingsnakecase`

Takes the `value` string, and turns it into SCREAMING_SNAKE case. Optionally, you can pass in the existing case of the function, or else we will try to figure out the case automatically.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to convert to SCREAMING_SNAKE case. | | yes|
| original_case | string | Optional hint on the original case type. Must be one of: kebab-case, camelCase, PascalCase, SCREAMING_SNAKE, snake_case | | |

SCREAMING_SNAKE_CASE a string without specifying original case:

```ripsaw
screamingsnakecase("input-string")

# returns INPUT_STRING
```


SCREAMING_SNAKE_CASE a snake_case string:

```ripsaw
screamingsnakecase("foo_bar_baz", "snake_case")

# returns FOO_BAR_BAZ
```


SCREAMING_SNAKE_CASE specifying the wrong original case (capitalizes but doesn't include `_` properly):

```ripsaw
screamingsnakecase("FooBarBaz", "kebab-case")

# returns FOOBARBAZ
```

### `sieve`

Keeps only matches of `pattern` in `value`.

This can be used to define patterns that are allowed in the string and
remove everything else.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The original string. | | yes|
| permitted_characters | regex | Keep all matches of this pattern. | | yes|
| replace_single | string | The string to use to replace single rejected characters. | | |
| replace_repeated | string | The string to use to replace multiple sequential instances of rejected characters. | | |

Keep only lowercase letters:

```ripsaw
sieve("example.com/lowerUPPER", permitted_characters: r'[a-z]')

# returns examplecomlower
```


Sieve with regex:

```ripsaw
sieve("test123%456.فوائد.net.", r'[a-z0-9.]')

# returns test123456..net.
```


Custom replacements:

```ripsaw
sieve("test123%456.فوائد.net.", r'[a-z.0-9]', replace_single: "X", replace_repeated: "<REMOVED>")

# returns test123X456.<REMOVED>.net.
```

### `slice`

Returns a slice of `value` between the `start` and `end` positions.

If the `start` and `end` parameters are negative, they refer to positions counting from the right of the
string or array. If `end` refers to a position that is greater than the length of the string or array,
a slice up to the end of the string or array is returned.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string/array | The string or array to slice. | | yes|
| start | integer | The inclusive start position. A zero-based index that can be negative. | | yes|
| end | integer | The exclusive end position. A zero-based index that can be negative. | String length| |

Slice a string (positive index):

```ripsaw
slice!("Supercalifragilisticexpialidocious", start: 5, end: 13)

# returns califrag
```


Slice a string (negative index):

```ripsaw
slice!("Supercalifragilisticexpialidocious", start: 5, end: -14)

# returns califragilistic
```


String start:

```ripsaw
slice!("foobar", 3)

# returns bar
```


Array start:

```ripsaw
slice!([0, 1, 2], 1)

# returns [1,2]
```

### `snakecase`

Takes the `value` string, and turns it into snake_case. Optionally, you can pass in the existing case of the function, or else we will try to figure out the case automatically.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to convert to snake_case. | | yes|
| original_case | string | Optional hint on the original case type. Must be one of: kebab-case, camelCase, PascalCase, SCREAMING_SNAKE, snake_case | | |
| excluded_boundaries | array of strings | Case boundaries to exclude during conversion. | | |

snake_case a string:

```ripsaw
snakecase("input-string")

# returns input_string
```


snake_case a string with original case:

```ripsaw
snakecase("input-string", original_case: "kebab-case")

# returns input_string
```


snake_case with excluded boundaries:

```ripsaw
snakecase("s3BucketDetails", excluded_boundaries: ["lower_digit"])

# returns s3_bucket_details
```

### `split`

Splits the `value` string using `pattern`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to split. | | yes|
| pattern | regex | The string is split whenever this pattern is matched. | | yes|
| limit | integer | The maximum number of substrings to return. | | |

Split a string (no limit):

```ripsaw
split("apples and pears and bananas", " and ")

# returns ["apples","pears","bananas"]
```


Split a string (with a limit):

```ripsaw
split("apples and pears and bananas", " and ", limit: 2)

# returns ["apples","pears and bananas"]
```


Split string:

```ripsaw
split("foobar", "b")

# returns ["foo","ar"]
```


Split regex:

```ripsaw
split("barbaz", r'ba')

# returns ["","r","z"]
```

### `split_path`

Splits the given `path` into its constituent components, returning an array of strings. Each component represents a part of the file system path hierarchy.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | path | The path to split into components. | | yes|

Split path with trailing slash:

```ripsaw
split_path("/home/user/")

# returns ["/","home","user"]
```


Split path from file path:

```ripsaw
split_path("/home/user")

# returns ["/","home","user"]
```


Split path from root:

```ripsaw
split_path("/")

# returns ["/"]
```


Empty path returns empty array:

```ripsaw
split_path("")

# returns []
```

### `starts_with`

Determines whether `value` begins with `substring`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to search. | | yes|
| substring | string | The substring that the `value` must start with. | | yes|
| case_sensitive | boolean | Whether the match should be case sensitive. | true| |

String starts with (case sensitive):

```ripsaw
starts_with("The Needle In The Haystack", "The Needle")

# returns true
```


String starts with (case insensitive):

```ripsaw
starts_with("The Needle In The Haystack", "the needle", case_sensitive: false)

# returns true
```


String starts with (case sensitive failure):

```ripsaw
starts_with("foobar", "F")


```

### `truncate`

Truncates the `value` string up to the `limit` number of characters.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to truncate. | | yes|
| limit | integer | The number of characters to truncate the string after. | | yes|
| suffix | string | A custom suffix to be appended to truncated strings. If a custom `suffix` is
provided, the total length of the string will be `limit + <suffix length>`. | | |

Truncate a string:

```ripsaw
truncate("A rather long sentence.", limit: 11, suffix: "...")

# returns A rather lo...
```


Truncate a string (custom suffix):

```ripsaw
truncate("A rather long sentence.", limit: 11, suffix: "[TRUNCATED]")

# returns A rather lo[TRUNCATED]
```


Truncate:

```ripsaw
truncate("foobar", 3)

# returns foo
```

### `upcase`

Upcases `value`, where upcase is defined according to the Unicode Derived Core Property Uppercase.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The string to convert to uppercase. | | yes|

Upcase a string:

```ripsaw
upcase("Hello, World!")

# returns HELLO, WORLD!
```


## Timestamp functions

### `format_timestamp`

Formats `value` into a string representation of the timestamp.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | timestamp | The timestamp to format as text. | | yes|
| format | string | The format string as described by the [Chrono library](https://docs.rs/chrono/latest/chrono/format/strftime/index.html#specifiers). | | yes|
| timezone | string | The timezone to use when formatting the timestamp. The parameter uses the TZ identifier or `local`. | | |

Format a timestamp (ISO8601/RFC 3339):

```ripsaw
format_timestamp!(t'2020-10-21T16:00:00Z', format: "%+")

# returns 2020-10-21T16:00:00+00:00
```


Format a timestamp (custom):

```ripsaw
format_timestamp!(t'2020-10-21T16:00:00Z', format: "%v %R")

# returns 21-Oct-2020 16:00
```


Format a timestamp with custom format string:

```ripsaw
format_timestamp!(t'2021-02-10T23:32:00+00:00', format: "%d %B %Y %H:%M")

# returns 10 February 2021 23:32
```


Format a timestamp with timezone conversion:

```ripsaw
format_timestamp!(t'2021-02-10T23:32:00+00:00', format: "%d %B %Y %H:%M", timezone: "Europe/Berlin")

# returns 11 February 2021 00:32
```

## Type functions

### `array`

Returns `value` if it is an array, otherwise returns an error. This enables the type checker to guarantee that the returned value is an array and can be used in any function that expects an array.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is an array. | | yes|

Declare an array type:

```ripsaw
array!(.value)

# returns [1,2,3]
```


Valid array literal:

```ripsaw
array([1,2,3])

# returns [1,2,3]
```


Invalid type:

```ripsaw
array!(true)


```

### `bool`

Returns `value` if it is a Boolean, otherwise returns an error. This enables the type
checker to guarantee that the returned value is a Boolean and can be used in any
function that expects a Boolean.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a Boolean. | | yes|

Valid Boolean:

```ripsaw
bool(false)


```


Invalid Boolean:

```ripsaw
bool!(42)


```


Valid Boolean from path:

```ripsaw
bool!(.value)

# returns true
```

### `float`

Returns `value` if it is a float, otherwise returns an error. This enables the type checker to guarantee that the returned value is a float and can be used in any function that expects a float.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a float. | | yes|

Declare a float type:

```ripsaw
. = { "value": 42.0 }
float(.value)


# returns 42.0
```


Declare a float type (literal):

```ripsaw
float(3.1415)

# returns 3.1415
```


Invalid float type:

```ripsaw
float!(true)


```

### `int`

Returns `value` if it is an integer, otherwise returns an error. This enables the type checker to guarantee that the returned value is an integer and can be used in any function that expects an integer.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is an integer. | | yes|

Declare an integer type:

```ripsaw
. = { "value": 42 }
int(.value)


# returns 42
```


Declare an integer type (literal):

```ripsaw
int(42)

# returns 42
```


Invalid integer type:

```ripsaw
int!(true)


```

### `is_array`

Check if the `value`'s type is an array.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is an array. | | yes|

Valid array:

```ripsaw
is_array([1, 2, 3])

# returns true
```


Non-matching type:

```ripsaw
is_array("a string")


```


Boolean:

```ripsaw
is_array(true)


```


Null:

```ripsaw
is_array(null)


```

### `is_boolean`

Check if the `value`'s type is a boolean.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a Boolean. | | yes|

Valid boolean:

```ripsaw
is_boolean(false)

# returns true
```


Non-matching type:

```ripsaw
is_boolean("a string")


```


Null:

```ripsaw
is_boolean(null)


```

### `is_empty`

Check if the object, array, or string has a length of `0`.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | object/array/string | The value to check. | | yes|

Empty array:

```ripsaw
is_empty([])

# returns true
```


Non-empty string:

```ripsaw
is_empty("a string")


```


Non-empty object:

```ripsaw
is_empty({"foo": "bar"})


```


Empty string:

```ripsaw
is_empty("")

# returns true
```


Empty object:

```ripsaw
is_empty({})

# returns true
```


Non-empty array:

```ripsaw
is_empty([1,2,3])


```

### `is_float`

Check if the `value`'s type is a float.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a float. | | yes|

Valid float:

```ripsaw
is_float(0.577)

# returns true
```


Non-matching type:

```ripsaw
is_float("a string")


```


Boolean:

```ripsaw
is_float(true)


```


Null:

```ripsaw
is_float(null)


```

### `is_integer`

Check if the `value`'s type is an integer.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is an integer. | | yes|

Valid integer:

```ripsaw
is_integer(1)

# returns true
```


Non-matching type:

```ripsaw
is_integer("a string")


```


Null:

```ripsaw
is_integer(null)


```

### `is_json`

Check if the string is a valid JSON document.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | string | The value to check if it is a valid JSON document. | | yes|
| variant | string | The variant of the JSON type to explicitly check for. | | |

Valid JSON object:

```ripsaw
is_json("{}")

# returns true
```


Non-valid value:

```ripsaw
is_json("{")


```


Exact variant:

```ripsaw
is_json("{}", variant: "object")

# returns true
```


Non-valid exact variant:

```ripsaw
is_json("{}", variant: "array")


```


Valid JSON string:

```ripsaw
is_json(s'"test"')

# returns true
```

### `is_null`

Check if `value`'s type is `null`. For a more relaxed function, see [`is_nullish`](#is_nullish).

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is `null`. | | yes|

Null value:

```ripsaw
is_null(null)

# returns true
```


Non-matching type:

```ripsaw
is_null("a string")


```


Array:

```ripsaw
is_null([1, 2, 3])


```

### `is_nullish`

Determines whether `value` is nullish. Returns `true` if the specified `value` is `null`, an empty string, a string containing only whitespace, or the string `"-"`. Returns `false` otherwise.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check for nullishness, for example, a useless value. | | yes|

Null detection (blank string):

```ripsaw
is_nullish("")

# returns true
```


Null detection (dash string):

```ripsaw
is_nullish("-")

# returns true
```


Null detection (whitespace):

```ripsaw
is_nullish("

")

# returns true
```


Null:

```ripsaw
is_nullish(null)

# returns true
```

### `is_object`

Check if `value`'s type is an object.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is an object. | | yes|

Valid object:

```ripsaw
is_object({"foo": "bar"})

# returns true
```


Non-matching type:

```ripsaw
is_object("a string")


```


Boolean:

```ripsaw
is_object(true)


```

### `is_regex`

Check if `value`'s type is a regex.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a regex. | | yes|

Valid regex:

```ripsaw
is_regex(r'pattern')

# returns true
```


Non-matching type:

```ripsaw
is_regex("a string")


```


Null value:

```ripsaw
is_regex(null)


```

### `is_string`

Check if `value`'s type is a string.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a string. | | yes|

Valid string:

```ripsaw
is_string("a string")

# returns true
```


Non-matching type:

```ripsaw
is_string([1, 2, 3])


```


Boolean:

```ripsaw
is_string(true)


```


Null:

```ripsaw
is_string(null)


```

### `is_timestamp`

Check if `value`'s type is a timestamp.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a timestamp. | | yes|

Valid timestamp:

```ripsaw
is_timestamp(t'2021-03-26T16:00:00Z')

# returns true
```


Non-matching type:

```ripsaw
is_timestamp("a string")


```


Boolean value:

```ripsaw
is_timestamp(true)


```

### `object`

Returns `value` if it is an object, otherwise returns an error. This enables the type checker to guarantee that the returned value is an object and can be used in any function that expects an object.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is an object. | | yes|

Declare an object type:

```ripsaw
. = { "value": { "field1": "value1", "field2": "value2" } }
object(.value)


# returns {"field1":"value1","field2":"value2"}
```


Invalid type:

```ripsaw
object!(true)


```

### `string`

Returns `value` if it is a string, otherwise returns an error. This enables the type checker to guarantee that the returned value is a string and can be used in any function that expects a string.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a string. | | yes|

Declare a string type:

```ripsaw
. = { "message": "{\"field\": \"value\"}" }
string(.message)


# returns {"field": "value"}
```


Invalid type:

```ripsaw
string!(true)


```

### `tag_types_externally`

Adds type information to all (nested) scalar values in the provided `value`.

The type information is added externally, meaning that `value` has the form of `"type": value` after this
transformation.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | array/object/null | The value to tag with types. | | yes|

Tag types externally (scalar):

```ripsaw
tag_types_externally(123)

# returns {"integer":123}
```


Tag types externally (object):

```ripsaw
tag_types_externally({
    "message": "Hello world",
    "request": {
        "duration_ms": 67.9
    }
})


# returns {"message":{"string":"Hello world"},"request":{"duration_ms":{"float":67.9}}}
```


Tag types externally (array):

```ripsaw
tag_types_externally(["foo", "bar"])

# returns [{"string":"foo"},{"string":"bar"}]
```


Tag types externally (null):

```ripsaw
tag_types_externally(null)


```

### `timestamp`

Returns `value` if it is a timestamp, otherwise returns an error. This enables the type checker to guarantee that the returned value is a timestamp and can be used in any function that expects a timestamp.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to check if it is a timestamp. | | yes|

Declare a timestamp type:

```ripsaw
timestamp(t'2020-10-10T16:00:00Z')

# returns t'2020-10-10T16:00:00Z'
```


Invalid type:

```ripsaw
timestamp!(true)


```

## Type Coercion functions

### `to_bool`

Coerces the `value` into a boolean.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to convert to a Boolean. | | yes|

Coerce to a Boolean (string):

```ripsaw
to_bool!("yes")

# returns true
```


Coerce to a Boolean (float):

```ripsaw
to_bool(0.0)


```


Coerce to a Boolean (int):

```ripsaw
to_bool(0)


```


Coerce to a Boolean (null):

```ripsaw
to_bool(null)


```


Coerce to a Boolean (Boolean):

```ripsaw
to_bool(true)

# returns true
```


Integer (other):

```ripsaw
to_bool(2)

# returns true
```


Float (other):

```ripsaw
to_bool(5.6)

# returns true
```


False:

```ripsaw
to_bool(false)


```


True string:

```ripsaw
to_bool!(s'true')

# returns true
```


Y string:

```ripsaw
to_bool!(s'y')

# returns true
```


Non-zero integer string:

```ripsaw
to_bool!(s'1')

# returns true
```


False string:

```ripsaw
to_bool!(s'false')


```


No string:

```ripsaw
to_bool!(s'no')


```


N string:

```ripsaw
to_bool!(s'n')


```


Invalid string:

```ripsaw
to_bool!(s'foobar')


```


Timestamp:

```ripsaw
to_bool!(t'2020-01-01T00:00:00Z')


```


Array:

```ripsaw
to_bool!([])


```


Object:

```ripsaw
to_bool!({})


```


Regex:

```ripsaw
to_bool!(r'foo')


```

### `to_float`

Coerces the `value` into a float.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to convert to a float. Must be convertible to a float, otherwise an error is raised. | | yes|

Coerce to a float:

```ripsaw
to_float!("3.145")

# returns 3.145
```


Coerce to a float (timestamp):

```ripsaw
to_float(t'2020-12-30T22:20:53.824727Z')

# returns 1609366853.824727
```


Integer:

```ripsaw
to_float(5)

# returns 5.0
```


Float:

```ripsaw
to_float(5.6)

# returns 5.6
```


True:

```ripsaw
to_float(true)

# returns 1.0
```


False:

```ripsaw
to_float(false)

# returns 0.0
```


Null:

```ripsaw
to_float(null)

# returns 0.0
```


Invalid string:

```ripsaw
to_float!(s'foobar')


```


Array:

```ripsaw
to_float!([])


```


Object:

```ripsaw
to_float!({})


```


Regex:

```ripsaw
to_float!(r'foo')


```

### `to_int`

Coerces the `value` into an integer.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to convert to an integer. | | yes|

Coerce to an int (string):

```ripsaw
to_int!("2")

# returns 2
```


Coerce to an int (timestamp):

```ripsaw
to_int(t'2020-12-30T22:20:53.824727Z')

# returns 1609366853
```


Integer:

```ripsaw
to_int(5)

# returns 5
```


Float:

```ripsaw
to_int(5.6)

# returns 5
```


True:

```ripsaw
to_int(true)

# returns 1
```


False:

```ripsaw
to_int(false)

# returns 0
```


Null:

```ripsaw
to_int(null)

# returns 0
```


Invalid string:

```ripsaw
to_int!(s'foobar')


```


Array:

```ripsaw
to_int!([])


```


Object:

```ripsaw
to_int!({})


```


Regex:

```ripsaw
to_int!(r'foo')


```

### `to_regex`

Coerces the `value` into a regex.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | The value to convert to a regex. | | yes|

Coerce to a regex:

```ripsaw
to_regex!("^foo$")

# returns r'^foo$'
```

### `to_string`

Coerces the `value` into a string.

| Parameter | Type   | Description                 | Default | Required |
|-----------|--------|-----------------------------|---------|----------|
| value | any | The value to convert to a string. | | yes|

Coerce to a string (Boolean):

```ripsaw
to_string(true)

# returns s'true'
```


Coerce to a string (int):

```ripsaw
to_string(52)

# returns s'52'
```


Coerce to a string (float):

```ripsaw
to_string(52.2)

# returns s'52.2'
```


String:

```ripsaw
to_string(s'foo')

# returns foo
```


False:

```ripsaw
to_string(false)

# returns s'false'
```


Null:

```ripsaw
to_string(null)

# returns
```


Timestamp:

```ripsaw
to_string(t'2020-01-01T00:00:00Z')

# returns 2020-01-01T00:00:00Z
```


Array:

```ripsaw
to_string!([])


```


Object:

```ripsaw
to_string!({})


```


Regex:

```ripsaw
to_string!(r'foo')


```

