diff --git a/app/app.go b/app/app.go
index b358e3bc4..9fbaa07ad 100644
--- a/app/app.go
+++ b/app/app.go
@@ -15,7 +15,7 @@ const (
version = "%d.%d.%d"
Major = 5
Minor = 1
- Revision = 2000
+ Revision = 2100
)
// Copyright is the copyright owner string
diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go
index 5470ad139..15a24dd96 100644
--- a/builtins/docs/summaries.go
+++ b/builtins/docs/summaries.go
@@ -272,7 +272,8 @@ func init() {
"parser/equ": "Evaluate a mathematical function (deprecated)",
"parser/greater-than-greater-than": "Writes STDIN to disk - appending contents if file already exists",
"parser/pipe-append": "Redirects STDOUT to a file and append its contents",
- "parser/elvis": "Returns the right operand if the left operand is empty",
+ "parser/elvis": "Returns the right operand if the left operand is falsy",
+ "parser/null-coalescing": "Returns the right operand if the left operand is empty / undefined",
"parser/pipe-err": "Pipes STDERR from the left hand command to STDIN of the right hand command",
"parser/range": "Outputs a ranged subset of data from STDIN",
"parser/element": "Outputs an element from a nested structure",
@@ -729,6 +730,7 @@ func init() {
"parser/fappend": "parser/greater-than-greater-than",
"parser/pipe-append": "parser/pipe-append",
"parser/elvis": "parser/elvis",
+ "parser/null-coalescing": "parser/null-coalescing",
"parser/pipe-err": "parser/pipe-err",
"parser/@[": "parser/range",
"parser/[[": "parser/element",
diff --git a/docs/parser/README.md b/docs/parser/README.md
index ec548fe53..5d926faaa 100644
--- a/docs/parser/README.md
+++ b/docs/parser/README.md
@@ -56,7 +56,9 @@ files.
* [`>>` Append Pipe](../parser/pipe-append.md):
Redirects STDOUT to a file and append its contents
* [`?:` Elvis Operator](../parser/elvis.md):
- Returns the right operand if the left operand is empty
+ Returns the right operand if the left operand is falsy
+* [`??` Null Coalescing Operator](../parser/null-coalescing.md):
+ Returns the right operand if the left operand is empty / undefined
* [`?` STDERR Pipe](../parser/pipe-err.md):
Pipes STDERR from the left hand command to STDIN of the right hand command
* [`[..range]`](../parser/range.md):
diff --git a/docs/parser/elvis.md b/docs/parser/elvis.md
index 93317df82..98f04c99c 100644
--- a/docs/parser/elvis.md
+++ b/docs/parser/elvis.md
@@ -1,16 +1,21 @@
# `?:` Elvis Operator
-> Returns the right operand if the left operand is empty
+> Returns the right operand if the left operand is falsy
## Description
The elvis operator is a little like a conditional where the result of the
-operation is the first non-empty value from left to right.
+operation is the first non-falsy value from left to right.
-An empty value is any of the following:
+A falsy value is any of the following:
-* An unset / undefined variable
-* Any value with a `null` data type
+* an unset / undefined variable
+* any value with a `null` data type
+* a `str` or generic with the value `false`, `null`, `0`, `no`, `off`, `fail`,
+ `failed`, or `disabled`
+* a number (`num`, `float` or `int`) with the value `0`
+* an empty object or zero length array
+* and, of course, a boolean with the value `false`
Other "falsy" values such as numerical values of `0`, boolean `false`, zero
length strings and strings containing `"null"` are not considered empty by the
@@ -31,7 +36,7 @@ If `$bar` is unset then the value of `$foo` will be **"baz"**.
**Multiple elvis operators:**
```
-» $unset_variable ?: null ?: "foobar"
+» $unset_variable ?: null ?: false ?: "foobar"
foobar
```
@@ -54,6 +59,8 @@ where it says:
Overview of the different schedulers (or 'run modes') in Murex
* [`&&` And Logical Operator](../parser/logical-and.md):
Continues next operation if previous operation passes
+* [`??` Null Coalescing Operator](../parser/null-coalescing.md):
+ Returns the right operand if the left operand is empty / undefined
* [`?` STDERR Pipe](../parser/pipe-err.md):
Pipes STDERR from the left hand command to STDIN of the right hand command
* [`err`](../commands/err.md):
diff --git a/docs/parser/logical-and.md b/docs/parser/logical-and.md
index 8b94f366d..1fbc9835e 100644
--- a/docs/parser/logical-and.md
+++ b/docs/parser/logical-and.md
@@ -48,7 +48,7 @@ try {
* [Schedulers](../user-guide/schedulers.md):
Overview of the different schedulers (or 'run modes') in Murex
* [`?:` Elvis Operator](../parser/elvis.md):
- Returns the right operand if the left operand is empty
+ Returns the right operand if the left operand is falsy
* [`?` STDERR Pipe](../parser/pipe-err.md):
Pipes STDERR from the left hand command to STDIN of the right hand command
* [`err`](../commands/err.md):
diff --git a/docs/parser/logical-or.md b/docs/parser/logical-or.md
index eb7a8291c..85c2fe701 100644
--- a/docs/parser/logical-or.md
+++ b/docs/parser/logical-or.md
@@ -53,7 +53,7 @@ There is no workaround for `trypipe`.
* [`&&` And Logical Operator](../parser/logical-and.md):
Continues next operation if previous operation passes
* [`?:` Elvis Operator](../parser/elvis.md):
- Returns the right operand if the left operand is empty
+ Returns the right operand if the left operand is falsy
* [`?` STDERR Pipe](../parser/pipe-err.md):
Pipes STDERR from the left hand command to STDIN of the right hand command
* [`err`](../commands/err.md):
diff --git a/docs/parser/null-coalescing.md b/docs/parser/null-coalescing.md
new file mode 100644
index 000000000..52d1e88ca
--- /dev/null
+++ b/docs/parser/null-coalescing.md
@@ -0,0 +1,84 @@
+# `??` Null Coalescing Operator
+
+> Returns the right operand if the left operand is empty / undefined
+
+## Description
+
+The null coalescing operator is a little like a conditional where the result of the
+operation is the first non-empty value from left to right.
+
+An empty value is any of the following:
+
+* an unset / undefined variable
+* any value with a `null` data type
+
+Other "falsy" values such as numerical values of `0`, boolean `false`, zero
+length strings and strings containing `"null"` are not considered empty by the
+null coalescing operator.
+
+
+
+## Examples
+
+**Assign a variable with a default value:**
+
+```
+» $foo = $bar ?? "baz"
+```
+
+If `$bar` is unset then the value of `$foo` will be **"baz"**.
+
+**Multiple operators:**
+
+```
+» $unset_variable ?? null ?? "foobar"
+foobar
+```
+
+## Detail
+
+The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/Null_coalescing_operator):
+
+> The null coalescing operator (called the Logical Defined-Or operator in Perl)
+> is a binary operator that is part of the syntax for a basic conditional
+> expression in several programming languages, including C#, PowerShell as of
+> version 7.0.0, Perl as of version 5.10, Swift, and PHP 7.0.0. While its
+> behavior differs between implementations, the null coalescing operator
+> generally returns the result of its left-most operand if it exists and is not
+> null, and otherwise returns the right-most operand. This behavior allows a
+> default value to be defined for cases where a more specific value is not
+> available.
+>
+> In contrast to the ternary conditional if operator used as `x ? x : y`, but
+> like the binary Elvis operator used as `x ?: y`, the null coalescing operator
+> is a binary operator and thus evaluates its operands at most once, which is
+> significant if the evaluation of `x` has side-effects.
+
+## See Also
+
+* [Pipeline](../user-guide/pipeline.md):
+ Overview of what a "pipeline" is
+* [Schedulers](../user-guide/schedulers.md):
+ Overview of the different schedulers (or 'run modes') in Murex
+* [`&&` And Logical Operator](../parser/logical-and.md):
+ Continues next operation if previous operation passes
+* [`?:` Elvis Operator](../parser/elvis.md):
+ Returns the right operand if the left operand is falsy
+* [`?` STDERR Pipe](../parser/pipe-err.md):
+ Pipes STDERR from the left hand command to STDIN of the right hand command
+* [`err`](../commands/err.md):
+ Print a line to the STDERR
+* [`out`](../commands/out.md):
+ Print a string to the STDOUT with a trailing new line character
+* [`try`](../commands/try.md):
+ Handles errors inside a block of code
+* [`trypipe`](../commands/trypipe.md):
+ Checks state of each function in a pipeline and exits block on error
+* [`||` Or Logical Operator](../parser/logical-or.md):
+ Continues next operation only if previous operation fails
+* [null](../commands/devnull.md):
+ null function. Similar to /dev/null
+
+
+
+This document was generated from [gen/parser/null_coalescing_op_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/parser/null_coalescing_op_doc.yaml).
\ No newline at end of file
diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md
index 0e6456978..8fe295fc3 100644
--- a/docs/user-guide/README.md
+++ b/docs/user-guide/README.md
@@ -94,7 +94,9 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language.
* [`>>` Append Pipe](parser/pipe-append.md):
Redirects STDOUT to a file and append its contents
* [`?:` Elvis Operator](parser/elvis.md):
- Returns the right operand if the left operand is empty
+ Returns the right operand if the left operand is falsy
+* [`??` Null Coalescing Operator](parser/null-coalescing.md):
+ Returns the right operand if the left operand is empty / undefined
* [`?` STDERR Pipe](parser/pipe-err.md):
Pipes STDERR from the left hand command to STDIN of the right hand command
* [`[..range]`](parser/range.md):
diff --git a/docs/user-guide/rosetta-stone.md b/docs/user-guide/rosetta-stone.md
index bdc110e88..fe8504952 100644
--- a/docs/user-guide/rosetta-stone.md
+++ b/docs/user-guide/rosetta-stone.md
@@ -88,11 +88,11 @@ if you want to learn more about shell scripting in Murex.
### Variables
| Description | Bash | Murex |
|---------------|---------------|--------|
-| [Printing a variable](../parser/string.md) | `echo "$foobar"` | `out $foobar` [[5]](#footnotes)
`$foobar`
(variables don't need to be quoted in Murex) |
+| [Printing a variable](../parser/scalar.md) | `echo "$foobar"` | `out $foobar` [[5]](#footnotes)
`$foobar`
(variables don't need to be quoted in Murex) |
| [Assign a local variable](../commands/set.md) | `local foo="bar"` | `$foo = "bar"` [[2]](#footnotes) [[6]](#footnotes)
`out "bar" \| set $foo` |
| [Assign a global variable](../commands/global.md) | `foo="bar"` | `$GLOBAL.foo = "bar"` [[6]](#footnotes)
`out "bar" \| export $foo` [[3]](#footnotes) |
-| Assign with a default value | `FOOBAR="${VARIABLE:-default}"` | `$foobar = $variable ?: "default"`
(the elvis operator can be used in any part of expressions and just for assignments)
+| [Assign with a default value](../parser/null-coalescing.md) | `FOOBAR="${VARIABLE:-default}"` | `$foobar = $variable ?: "default"`
(the elvis operator can be used in any part of expressions and just for assignments)
### Arrays
(eg arrays, lists)
diff --git a/gen/parser/elvis_op_doc.yaml b/gen/parser/elvis_op_doc.yaml
index 9396a5f3f..e5ffc99f3 100644
--- a/gen/parser/elvis_op_doc.yaml
+++ b/gen/parser/elvis_op_doc.yaml
@@ -3,15 +3,20 @@
`?:` Elvis Operator
CategoryID: parser
Summary: >-
- Returns the right operand if the left operand is empty
+ Returns the right operand if the left operand is falsy
Description: |-
The elvis operator is a little like a conditional where the result of the
- operation is the first non-empty value from left to right.
+ operation is the first non-falsy value from left to right.
- An empty value is any of the following:
+ A falsy value is any of the following:
- * An unset / undefined variable
- * Any value with a `null` data type
+ * an unset / undefined variable
+ * any value with a `null` data type
+ * a `str` or generic with the value `false`, `null`, `0`, `no`, `off`, `fail`,
+ `failed`, or `disabled`
+ * a number (`num`, `float` or `int`) with the value `0`
+ * an empty object or zero length array
+ * and, of course, a boolean with the value `false`
Other "falsy" values such as numerical values of `0`, boolean `false`, zero
length strings and strings containing `"null"` are not considered empty by the
@@ -28,7 +33,7 @@
**Multiple elvis operators:**
```
- » $unset_variable ?: null ?: "foobar"
+ » $unset_variable ?: null ?: false ?: "foobar"
foobar
```
Detail: |-
@@ -41,6 +46,7 @@
> ?:, is viewed sideways, it resembles an emoticon of Elvis Presley with his
> signature hairstyle.
Related:
+ - null-coalescing
- pipe-err
- pipeline
- schedulers
diff --git a/gen/parser/null_coalescing_op_doc.yaml b/gen/parser/null_coalescing_op_doc.yaml
new file mode 100644
index 000000000..70c98bb05
--- /dev/null
+++ b/gen/parser/null_coalescing_op_doc.yaml
@@ -0,0 +1,62 @@
+- DocumentID: null-coalescing
+ Title: >-
+ `??` Null Coalescing Operator
+ CategoryID: parser
+ Summary: >-
+ Returns the right operand if the left operand is empty / undefined
+ Description: |-
+ The null coalescing operator is a little like a conditional where the result of the
+ operation is the first non-empty value from left to right.
+
+ An empty value is any of the following:
+
+ * an unset / undefined variable
+ * any value with a `null` data type
+
+ Other "falsy" values such as numerical values of `0`, boolean `false`, zero
+ length strings and strings containing `"null"` are not considered empty by the
+ null coalescing operator.
+ Examples: |-
+ **Assign a variable with a default value:**
+
+ ```
+ » $foo = $bar ?? "baz"
+ ```
+
+ If `$bar` is unset then the value of `$foo` will be **"baz"**.
+
+ **Multiple operators:**
+
+ ```
+ » $unset_variable ?? null ?? "foobar"
+ foobar
+ ```
+ Detail: |-
+ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/Null_coalescing_operator):
+
+ > The null coalescing operator (called the Logical Defined-Or operator in Perl)
+ > is a binary operator that is part of the syntax for a basic conditional
+ > expression in several programming languages, including C#, PowerShell as of
+ > version 7.0.0, Perl as of version 5.10, Swift, and PHP 7.0.0. While its
+ > behavior differs between implementations, the null coalescing operator
+ > generally returns the result of its left-most operand if it exists and is not
+ > null, and otherwise returns the right-most operand. This behavior allows a
+ > default value to be defined for cases where a more specific value is not
+ > available.
+ >
+ > In contrast to the ternary conditional if operator used as `x ? x : y`, but
+ > like the binary Elvis operator used as `x ?: y`, the null coalescing operator
+ > is a binary operator and thus evaluates its operands at most once, which is
+ > significant if the evaluation of `x` has side-effects.
+ Related:
+ - elvis
+ - pipe-err
+ - pipeline
+ - schedulers
+ - out
+ - err
+ - try
+ - trypipe
+ - logical-and
+ - logical-or
+ - "null"
diff --git a/gen/user-guide/rosetta-stone.inc.md b/gen/user-guide/rosetta-stone.inc.md
index 70c66bb3e..291d1b2ab 100644
--- a/gen/user-guide/rosetta-stone.inc.md
+++ b/gen/user-guide/rosetta-stone.inc.md
@@ -84,11 +84,11 @@ if you want to learn more about shell scripting in Murex.
### Variables
| Description | Bash | Murex |
|---------------|---------------|--------|
-| [Printing a variable](../parser/string.md) | `echo "$foobar"` | `out $foobar` [[5]](#footnotes)
`$foobar`
(variables don't need to be quoted in Murex) |
+| [Printing a variable](../parser/scalar.md) | `echo "$foobar"` | `out $foobar` [[5]](#footnotes)
`$foobar`
(variables don't need to be quoted in Murex) |
| [Assign a local variable](../commands/set.md) | `local foo="bar"` | `$foo = "bar"` [[2]](#footnotes) [[6]](#footnotes)
`out "bar" \| set $foo` |
| [Assign a global variable](../commands/global.md) | `foo="bar"` | `$GLOBAL.foo = "bar"` [[6]](#footnotes)
`out "bar" \| export $foo` [[3]](#footnotes) |
-| Assign with a default value | `FOOBAR="${VARIABLE:-default}"` | `$foobar = $variable ?: "default"`
(the elvis operator can be used in any part of expressions and just for assignments)
+| [Assign with a default value](../parser/null-coalescing.md) | `FOOBAR="${VARIABLE:-default}"` | `$foobar = $variable ?: "default"`