/** @page operators Operators

    @tableofcontents

    The following table lists all %Qore operators in order of precedence, starting with the highest precedence. The lower the precedence number, the higher the precedence, therefore the operators with precedence level 1 (\c "{}", \c "[]", \c ".") have the highest precedence of all %Qore operators. The precedence levels in %Qore are roughly equal to the precedence levels of C language operators. To explicitly specify the precedence for expression evaluation, use parentheses <tt>()</tt>.  Note that all examples are given in @ref new-style "%new-style".

    <b>Operators</b>
    |!Operator|!Prec.|!Description|!Example
    |@ref backquote_operator "``"|\c 1|@ref backquote_operator "backquote/backtick operator"|@code{.py} `ls -l`@endcode
    |@ref hash_element_operator "{}"|\c 1|@ref hash_element_operator "hash element or object member expression dereference operator"|@code{.py} hash{"na" + "me"}@endcode
    |@ref dot_operator "."|\c 1|@ref dot_operator "hash element or object member literal dereference operator"|@code{.py} hash.name@endcode @code{.py} obj.method()@endcode
    |@ref list_element_operator "[]"|\c 1|@ref list_element_operator "list element, string, and binary dereference operator"|@code{.py} list[1]; string[3]; binary[2];@endcode
    |@ref pre_increment_operator "++"|\c 2|@ref pre_increment_operator "pre-increment operator"|@code{.py} ++a@endcode
    |@ref post_increment_operator "++"|\c 2|@ref post_increment_operator "post-increment operator"|@code{.py} a++@endcode
    |@ref pre_decrement_operator "--"|\c 2|@ref pre_decrement_operator "pre-decrement operator"|@code{.py} --a@endcode
    |@ref post_decrement_operator "--"|\c 2|@ref post_decrement_operator "post-decrement operator"|@code{.py} a--@endcode
    |@ref new "new"|\c 3|@ref new "value instantiation/new operator"|@code{.py} new Socket()@endcode
    |@ref background "background"|\c 3|@ref background "background/thread creation operator"|@code{.py} background mainThread()@endcode
    |@ref delete "delete"|\c 3|@ref delete "delete operator"|@code{.py} delete var@endcode
    |@ref remove "remove"|\c 3|@ref remove "remove operator"|@code{.py} remove var@endcode
    |@ref cast "cast<>()"|\c 3|@ref cast "cast<>() operator"|@code{.py} cast<SubClass>(var)@endcode
    |@ref logical_negation_operator "!"|\c 4|@ref logical_negation_operator "logical negation operator"|@code{.py} if (!(a > 10)) {}@endcode
    |@ref binary_not_operator "~"|\c 5|@ref binary_not_operator "binary not/bit inversion operator"|@code{.py} var = ~var@endcode
    |@ref unary_plus_operator "+ (unary plus)"|\c 6|@ref unary_plus_operator "unary plus operator"|@code{.py} var = +var@endcode
    |@ref unary_minus_operator "- (unary minus)"|\c 6|@ref unary_minus_operator "unary minus operator"|@code{.py} var = -var@endcode
    |@ref shift "shift"|\c 7|@ref shift "shift list element operator"|@code{.py} shift list@endcode
    |@ref pop "pop"|\c 7|@ref pop "pop list element operator"|@code{.py} pop list@endcode
    |@ref chomp "chomp"|\c 7|@ref chomp "chomp end-of-line character operator"|@code{.py} chomp string@endcode
    |@ref trim "trim"|\c 7|@ref trim "trim characters operator"|@code{.py} trim string@endcode
    |@ref elements "elements"|\c 8|@ref elements "number of elements operator (list, hash, string, binary)"|@code{.py} elements list@endcode
    |@ref keys "keys"|\c 8|@ref keys "hash key list operator"|@code{.py} keys hash@endcode
    |@ref multiplication_operator "*"|\c 9|@ref multiplication_operator "multiplication operator"|@code{.py} var = a * 10@endcode
    |@ref division_operator "/"|\c 9|@ref division_operator "division operator"|@code{.py} var = a / 10@endcode
    |@ref modulo_operator "%"|\c 10|@ref modulo_operator "modulo operator"|@code{.py} var = a % 10@endcode
    |@ref plus_operator "+"|\c 11|@ref plus_operator "plus operator: string, binary, list, and hash concatenation, integer and float addition"|@code{.py} a + 10@endcode @code{.py} "hello" + "there"@endcode @code{.py} list + "new value"@endcode @code{.py} hash + ( "newkey" : 100 )@endcode
    |@ref minus_operator "-"|\c 11|@ref minus_operator "minus operator (arithmetic subtraction, hash key removal)"|@code{.py} a - 10@endcode
    |@ref shift_right_operator ">>"|\c 12|@ref shift_right_operator "bitwise shift right operator"|@code{.py} 0xff00 >> 8@endcode
    |@ref shift_left_operator "<<"|\c 12|@ref shift_left_operator "bitwise shift left operator"|@code{.py} 0xff00 << 8@endcode
    |@ref exists "exists"|\c 13|@ref exists "exists value operator"|@code{.py} exists var@endcode
    |@ref instanceof "instanceof"|\c 13|@ref instanceof "instanceof operator"|@code{.py} instanceof Qore::Mutex@endcode
    |@ref logical_less_than_operator "<"|\c 14|@ref logical_less_than_operator "Logical less than operator"|@code{.py} a < 10@endcode
    |@ref logical_greater_than_operator ">"|\c 14|@ref logical_greater_than_operator "Logical greater than operator"|@code{.py} a > 10@endcode
    |@ref logical_equality_operator "=="|\c 14|@ref logical_equality_operator "Logical equality operator"|@code{.py} a == 10@endcode
    |@ref logical_inequality_operator "!="|\c 14|@ref logical_inequality_operator "logical inequality operator"|@code{.py} a != 10@endcode
    |@ref logical_less_than_or_equals_operator "<="|\c 14|@ref logical_less_than_or_equals_operator "Logical less then or equals operator"|@code{.py} a <= 10@endcode
    |@ref logical_greater_than_or_equals_operator ">="|\c 14|@ref logical_greater_than_or_equals_operator "logical greater than or equals operator"|@code{.py} a >= 10@endcode
    |@ref logical_comparison_operator "<=>"|\c 14|@ref logical_comparison_operator "logical comparison operator"|@code{.py} a <=> b@endcode
    |@ref logical_absolute_equality_operator "==="|\c 14|@ref logical_absolute_equality_operator "absolute logical equality operator"|@code{.py} a === 10@endcode
    |@ref logical_absolute_inequality_operator "!=="|\c 14|@ref logical_absolute_inequality_operator "absolute logical inequality operator"|@code{.py} a !== 10@endcode
    |@ref regex_match_operator "=~ //"|\c 14|@ref regex_match_operator "regular expression match operator"|@code{.py} a =~ /text/@endcode
    |@ref regex_no_match_operator "!~ //"|\c 14|@ref regex_no_match_operator "regular expression no match operator"|@code{.py} a !~ /text/@endcode
    |@ref regex_subst_operator "=~ s///"|\c 14|@ref regex_subst_operator "regular expression substitution operator"|@code{.py} a =~ s/text/text/@endcode
    |@ref regex_extract_operator "=~ x//"|\c 14|@ref regex_extract_operator "regular expression pattern extraction operator"|@code{.py} a =~ x/(\w+):(\w+)/@endcode
    |@ref transliteration_operator "=~ tr"|\c 14|@ref transliteration_operator "transliteration operator"|@code{.py} a =~ tr/a-z/A-Z/@endcode
    |@ref bitwise_and_operator "&"|\c 15|@ref bitwise_and_operator "bitwise/binary AND operator"|@code{.py} a & 0xff@endcode
    |@ref bitwise_xor_operator "^"|\c 16|@ref bitwise_xor_operator "bitwise/binary XOR operator"|@code{.py} a ^ 0xff@endcode
    |@ref bitwise_or_operator "|"|\c 17|@ref bitwise_or_operator "bitwise/binary OR operator"|@code{.py} a | 0xff@endcode
    |@ref logical_and_operator "&&"|\c 18|@ref logical_and_operator "logical AND operator"|@code{.py} (a = 1) && (b < 10)@endcode
    |@ref logical_or_operator "||"|\c 19|@ref logical_or_operator "logical OR operator"|@code{.py} (a = 1) || (b < 10)@endcode
    |@ref range_operator ".. (range)"|\c 20|@ref range_operator "range operator"|@code{.py} 3..7@endcode
    |@ref conditional_operator "? :"|\c 21|@ref conditional_operator "conditional operator"|@code{.py} a == 2 ? "yes" : "no"@endcode
    |@ref null_coalescing_operator "??"|\c 21|@ref null_coalescing_operator "null coalescing operator"|@code{.py} any var = a ?? b@endcode
    |@ref value_coalescing_operator "?*"|\c 21|@ref value_coalescing_operator "value coalescing operator"|@code{.py} any var = a ?* b@endcode
    |@ref comma_operator ","|\c 22|@ref comma_operator "comma operator"|@code{.py} 1, 2, 3, 4, 5@endcode
    |@ref unshift "unshift"|\c 23|@ref unshift "unshift list element operator"|@code{.py} unshift list, val@endcode
    |@ref push "push"|\c 23|@ref push "push list element operator"|@code{.py} push list, val@endcode
    |@ref splice "splice"|\c 23|@ref splice "splice list or string operator"|@code{.py} splice list, 2, 2, (1, 2, 3)@endcode
    |@ref extract "extract"|\c 23|@ref extract "extract list or string operator"|@code{.py} my sublist = extract list, 2, 2, (1, 2, 3)@endcode
    |@ref map "map"|\c 23|@ref map "map operator"|@code{.py} map closure($1), list@endcode
    |@ref hmap "hash map"|\c 23|@ref hmap "hash map operator"|@code{.py} map {expr($1) : expr($1)}, list@endcode
    |@ref foldl "foldl"|\c 23|@ref foldl "fold left to right operator"|@code{.py} foldl closure($1 - $2), list@endcode
    |@ref foldr "foldr"|\c 23|@ref foldr "fold right to left operator"|@code{.py} foldr closure($1 - $2), list@endcode
    |@ref select "select"|\c 23|@ref select "select elements from list operator"|@code{.py} select list, $1 > 1@endcode
    |@ref assignment_operator "="|\c 24|@ref assignment_operator "assignment operator"|@code{.py} var = 1@endcode
    |@ref weak_assignment_operator ":="|\c 24|@ref weak_assignment_operator "weak assignment operator"|@code{.py} var := obj@endcode
    |@ref plus_equals_operator "+="|\c 24|@ref plus_equals_operator "plus-equals (add-to) operator"|@code{.py} var += 5@endcode
    |@ref minus_equals_operator "-="|\c 24|@ref minus_equals_operator "minus-equals (subtract-from) operator"|@code{.py} var -= 5@endcode
    |@ref and_equals_operator "&="|\c 24|@ref and_equals_operator "and-equals operator"|@code{.py} var &= 0x2000@endcode
    |@ref or_equals_operator "|="|\c 24|@ref or_equals_operator "or-equals operator"|@code{.py} var |= 0x2000@endcode
    |@ref modulo_equals_operator "%="|\c 24|@ref modulo_equals_operator "modulo-equals operator"|@code{.py} var %= 100@endcode
    |@ref multiply_equals_operator "*="|\c 24|@ref multiply_equals_operator "multiply-equals operator"|@code{.py} var *= 10@endcode
    |@ref divide_equals_operator "/="|\c 24|@ref divide_equals_operator "divide-equals operator"|@code{.py} var /= 10@endcode
    |@ref xor_equals_operator "^="|\c 24|@ref xor_equals_operator "xor-equals operator"|@code{.py} var ^= 0x2000@endcode
    |@ref shift_left_equals_operator "<<="|\c 24|@ref shift_left_equals_operator "shift-left-equals operator"|@code{.py} var <<= 0x2000@endcode
    |@ref shift_right_equals_operator ">>="|\c 24|@ref shift_right_equals_operator "shift-right-equals operator"|@code{.py} var >>= 0x2000@endcode

    @section op_atomicity Operator Atomicity

    All %Qore operators perform thread-atomic actions with respect to the immediate arguments of the operator.

    If more than one operator is used in an expression, the entire expression is not thread-atomic unless explicit user-level locking is used. For example: <tt>a += 5</tt> is a thread-atomic action, but <tt>a += b--</tt> is not atomic, but rather made up of two atomic actions.

    @section op_args Operator Arguments

    When an operator taking more than one argument is used with arguments of different data types, %Qore automatically converts one or both data types to a data type supported by the operator in order to evaluate the result, according to the precedence lists given for each operator. That is; when an operator operates on mixed types, the types listed first in the following sections have precedence over types listed farther down in the lists. The result type will always be equal to the final operation type after any conversions due to type precedence per operator. If no type of either argument matches a supported data type for the operator, both types will be converted to the highest precedence data type for the operator and then the operator will evaluate the result. For explicit type conversion, please see the boolean(), string(), date(), int(), float(), etc functions.

    @section op_functional Lazy Evalution of Functional Operators

    %Qore supports lazy evaluation of functional operators where possible in order to provide an efficient solution for processing large lists or nested functional operators.

    The following operators support lazy evaluation directly:
    - @ref map "map" (non-hash version): allows the @ref expressions "map expression" to be evaluated in place when nested with other functional operators or used with a @ref foreach "foreach statement"
    - @ref select "select": allows the filtered result list to be created and iterated in place when nested with other functional operators or used with a @ref foreach "foreach statement" rather than returning a temporary list
    - @ref keys "keys": allows the @ref hash "hash" or @ref object "object" to be iterated in place when nested with other functional operators or used with a @ref foreach "foreach statement" rather than returning a temporary list of hash keys or accessible object members
    - @ref range_operator ".. (range operator)" and @ref list_element_operator "[]" with a range or multiple values: allow the operand to be iterated in place when nested with other functional operators or used with a @ref foreach "foreach statement" rather than returning a temporary list/string/binary object

    The following operators and statements support lazy evaluation for iteration:
    - @ref map "map" (non-hash version): supports lazy evaluation in the @ref expressions "iterator expression" (and therefore nested lazy evaluation)
    - @ref select "select": supports lazy evaluation in the @ref expressions "iterator expression" (and therefore nested lazy evaluation)
    - @ref foldl "foldl": supports lazy evaluation in the @ref expressions "iterator expression"
    - @ref foldr "foldr": supports lazy evaluation in the @ref expressions "iterator expression"
    - @ref foreach "foreach": supports lazy evaluation in the @ref expressions "iterator expression"

    @par Example
    With lazy functional evaluation, the following code does not create a potentially long itermediate list with the @ref map "map" expression, but rather the @ref foldl "foldl" expression will operate directly on the expressions generated when iterating the value returned by <tt>get_iterator()</tt>:
    @code{.py}
# build a comma-separated string from an iterated expression
string str = foldl $1 + ", " + $2, (map $1.desc, get_iterator(), $1.type == External);
    @endcode

    @section op_details Operator Details

    <hr>
    @subsection backquote_operator Backquote Operator (``)

    @par Sandbox Restrictions
    @ref Qore::PO_NO_EXTERNAL_PROCESS

    @par Synopsis
    Executes the shell command in a separate process and returns the stdout as a string. To perform the same action using a %Qore expression, see the backquote() function.

    @par Syntax
    <tt>`</tt><em>shell_command</em><tt>`</tt>

    @par Return Type
    @ref string_type "string"

    @par Example
    @code{.py} string dir = `ls -l`@endcode

    <b>Arguments Processed by ``</b>
    |!Argument|!Returns|!Processing
    |unquoted @ref string "string" \a shell_command|@ref string_type "string"|The shell command will be executed and the \c stdout is returned as a string

    @throw BACKQUOTE-ERROR An error occurred in fork() or creating the output pipe

    <hr>
    @subsection hash_element_operator Hash Element or Object Member Expression Dereference Operator ({})

    @par Synopsis
    Retrieves the value of hash key or object member by evaulating an expression.

    @par Syntax
    <em>@ref expressions "container_expression"</em> <tt>{</tt> <em>@ref expressions "expression"</em> <tt>}</tt>

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} printf("%s\n", hash{getName()});@endcode

    <b>Arguments Processed by {}</b>
    |!Argument|!Processing
    |<em>@ref expressions "container_expression"</em>|This expression must evaluate to a @ref hash "hash" or an @ref object "object"; if not, the operator returns no value (@ref nothing)
    |<em>@ref expressions "expression"</em>|- @ref list "list": if the expression evaluates to a list, then a slice of the hash or object is returned as a hash containing keys given in the list that are present in the hash or object. If the key as given in the list (converted to a string if necessary) is not present in the hash or object, then it is also not present in the hash returned; if none of the given keys exist in the hash, an empty hash is returned.\n- anything other than @ref list "list": the expression is converted to a string (if necessary); the value of the hash key corresponding to this string will be returned; if the key or member does not exist, then no value is returned

    @throw PRIVATE-MEMBER Attempt to access a private member outside the class

    <hr>
    @subsection dot_operator Hash Element or Object Member Literal Dereference Operator (.)

    @par Synopsis
    Retrieves the value of a hash key or object member using a literal identifier or an expression.

    @par Syntax
    <em>@ref expressions "hash_or_object_expression"</em> <tt>.</tt> <i>identifier</i> \n
    <em>@ref expressions "object_expression"</em> <tt>.</tt> \a method_name<tt>(</tt><em>[args ...]</em><tt>)</tt>\n
    <em>@ref expressions "hash_or_object_expression"</em> <tt>.</tt> <i>expression</i> \n

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} printf("%s\n", hash.name);@endcode
    @code{.py} obj.method("argument");@endcode

    <b>Arguments Processed by . (hash key or object member literal dereference)</b>
    |!Argument|!Processing
    |<em>@ref expressions "hash_or_object_expression"</em>|This expression must evaluate to a hash or an object; if not, then the operator returns no value
    |\a identifier|An unquoted string taken as the literal name of the hash key or object member. If no such key exists, then no value is returned. In order to use hash keys that are not valid %Qore identifiers, please use the {} operator. If the member is a private member and access is made outside the class, a run-time exception will be thrown.  Also note that constants or static class member names will not be resolved, in this case the string given is used as the literal name of the hash key or object member

    <b>Arguments Processed by . (object method call)</b>
    |!Argument|!Processing
    |<em>@ref expressions "object_expression"</em>|The \a object_expression must evaluate to an object or a run-time exception is thrown
    |<em>method_name</em><tt>([</tt><em>args</em><tt>])</tt>|If the method does not exist in the class a run-time exception is thrown. Otherwise the method is called with any optional arguments given and the return value of the method is returned.

    <b>Arguments Processed by . (hash key or object member expression dereference)</b>
    |!Argument|!Processing
    |<em>@ref expressions "hash_or_object_expression"</em>|This expression must evaluate to a hash or an object; if not, then the operator returns no value
    |\a expression|- @ref list "list": if the expression evaluates to a list, then a slice of the hash or object is returned as a hash containing keys given in the list that are present in the hash or object. If the key as given in the list (converted to a string if necessary) is not present in the hash or object, then it is also not present in the hash returned; if none of the given keys exist in the hash, an empty hash is returned.\n- anything other than @ref list "list": the expression is converted to a string (if necessary); the value of the hash key corresponding to this string will be returned; if the key or member does not exist, then no value is returned

    @throw PRIVATE-MEMBER Attempt to access a private member outside the class
    @throw METHOD-DOES-NOT-EXIST Attempt to access a method not defined for this class
    @throw METHOD-IS-PRIVATE Attempt to access a private method from outside the class
    @throw BASE-CLASS-IS-PRIVATE Attempt to access a method of a privately-inherited base class from outside the class
    @throw OBJECT-METHOD-EVAL-ON-NON-OBJECT Attempt to execute a method on a non-object

    <hr>
    @subsection list_element_operator List, String, and Binary Dereference Operator ([])

    @par Synopsis
    Retrieves given list element(s), given character(s) of a string, or the integer value of given byte for a binary object or the binary object composed of given bytes of a binary object.
    If the index value is neither a list nor an integer it is converted to an integer. If the index is an integer and out of range, @ref nothing is returned.
    If the index is a list and completely out of range, empty list/string/binary is returned.
    Note that this operator is not supported with multiple values and/or ranges between the square brackets on the left-hand side of an assignment expression.

    @par Syntax
    <em>@ref expressions "list_expression"</em><tt>[</tt><em>@ref expressions "index_expression"</em><tt>]</tt>\n
    <em>@ref expressions "string_expression"</em><tt>[</tt><em>@ref expressions "index_expression"</em><tt>]</tt>\n
    <em>@ref expressions "binary_expression"</em><tt>[</tt><em>@ref expressions "index_expression"</em><tt>]</tt>\n

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py}
        int n = (6,2,7,4)[2];
        list l = (6,2,7,4)[3,1];
        list l = (6,2,7,4)[2..0];
        string s = "asdf"[2];
        string s = "asdf"[3,1];
        string s = "asdf"[1..];
        int hex = <4e8a23fe>[2];
        binary b = <4e8a23fe>[3,1];
        binary b = <4e8a23fe>[..2];
    @endcode

    <b>Arguments Processed by []</b>
    |!Argument|!Processing
    |<em>@ref expressions "list_expression"</em>|If the expression evaluates to a list, then the <em>@ref expressions "index_expression"</em> will be used to return the given element(s) from the list.
    |<em>@ref expressions "string_expression"</em>|If the expression evaluates to a string, then the <em>@ref expressions "index_expression"</em> will be used to return the given character(s) from the string; note that multi-byte characters with UTF-8 are properly respected with this operator.
    |<em>@ref expressions "binary_expression"</em>|If the expression evaluates to a binary, then the <em>@ref expressions "index_expression"</em> will be used to return the integer value of the given byte from the binary object or the binary object composed of the given bytes.
    |<em>@ref expressions "index_expression"</em>|If the expression does not evaluate to a list or to an integer it is converted to an integer. Then the value(s) of the given element(s) are returned according to the type of the first expression (as listed above; elements start at position 0). If the expression is in the range form (e.g. [1..3], [2..]) then the dereference operator supports @ref op_functional "lazy functional evaluation".

    This operator does not throw any exceptions; if the first expression does not evaluate to either a list, string, or binary, then no value (@ref nothing) is returned.

    @note this operator cannot be used on the left-hand side of an assignment expression with multiple values between square brackets

    @since %Qore 0.8.13 this operator accepts list expressions inside the square brackets

    <hr>
    @subsection pre_increment_operator Pre-Increment Operator (++)

    @par Synopsis
    Increments an lvalue and returns the incremented value; only works on integer and floating-point values.

    @par Syntax
    <tt>++</tt><em>lvalue</em>

    @par Return Type
    @ref int_type "int" or @ref float_type "float"

    @par Example
    @code{.py} ++i;@endcode

    <b>Arguments Processed by ++ (pre-increement)</b>
    |!Argument|!Processing
    |@ref float|increments \a lvalue and returns the result
    |@ref integer (or any other type)|First converts the value of \a lvalue to an integer if necessary, then increments \a lvalue and returns the result

    This operator does not throw any exceptions.

    <hr>
    @subsection post_increment_operator Integer Post-Increment Operator (++)

    @par Synopsis
    Increments an integer or floating-point lvalue and returns the value before the increment; if the \a lvalue is neither a floating-point value or an integer, it will be converted to an integer

    @par Syntax
    <em>lvalue</em><tt>++</tt>

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} i++;@endcode

    <b>Arguments Processed by ++ (post-increment)</b>
    |!Argument|!Processing
    |@ref float|saves the value of the \a lvalue as the result, then increments \a lvalue, then returns the saved original value of \a lvalue
    |@ref integer (or any other type)|saves the value of the \a lvalue as the result, then converts the value of \a lvalue to an integer if necessary and increments it, then returns the saved original value of \a lvalue

    This operator does not throw any exceptions.

    <hr>
    @subsection pre_decrement_operator Integer Pre-Decrement Operator (--)

    @par Synopsis
    Decrements an lvalue and returns the incremented value; only works on integer and floating-point values.

    @par Syntax
    <tt>--</tt><em>lvalue</em>

    @par Return Type
    @ref int_type "int" or @ref float_type "float"

    @par Example
    @code{.py} --i;@endcode

    <b>Arguments Processed by -- (pre-decrement)</b>
    |!Argument|!Processing
    |@ref float|increments \a lvalue and returns the result
    |@ref integer (or any other type)|First converts the value of \a lvalue to an integer if necessary, then increments \a lvalue and returns the result

    This operator does not throw any exceptions.

    <hr>
    @subsection post_decrement_operator Integer Post-Decrement Operator (--)

    @par Synopsis
    Decrements an integer or floating-point lvalue and returns the value before the decrement; if the \a lvalue is neither a floating-point value or an integer, it will be converted to an integer

    @par Syntax
    <em>lvalue</em><tt>--</tt>

    @par Return Type
    @ref any_type "any"

    @par Example
    i--;

    <b>Arguments Processed by -- (post-decrement)</b>
    |!Argument|!Processing
    |@ref float|saves the value of the \a lvalue as the result, then decrements \a lvalue, then returns the saved original value of \a lvalue
    |@ref integer (or any other type)|saves the value of the \a lvalue as the result, then converts the value of \a lvalue to an integer if necessary and decrements it, then returns the saved original value of \a lvalue

    This operator does not throw any exceptions.

    <hr>
    @subsection new New Value Operator (new)

    @par Sandbox Restrictions
    @ref Qore::PO_NO_NEW

    @par Synopsis
    This operator instantiates values according to the type and any argument(s) given.

    @par Syntax
    - <tt><b>new</b></tt> <em>@ref qore_classes "class_identifier"</em><tt>(</tt>[<em>constructor_args, ...</em>]<tt>)</tt>
    - <tt><b>new</b></tt> <tt>@ref object_type "object"&lt;</tt><em>@ref qore_classes "class_identifier"</em><tt>&gt;(</tt>[<em>constructor_args, ...</em>]<tt>)</tt>
    - <tt><b>new</b></tt> <tt>@ref hash_type "hash"&lt;</tt><em>@ref hashdecl "hashdecl_identifier"</em><tt>&gt;(</tt>[<em>hash_initializer_arg</em>]<tt>)</tt>
    - <tt><b>new</b></tt> <tt>@ref hash_type "hash"&lt;string, </tt><em>@ref data_type_declarations "type"</em><tt>&gt;(</tt>[<em>hash_initializer_arg</em>]<tt>)</tt>
    - <tt><b>new</b></tt> <tt>@ref list_type "list"&lt;</tt><em>@ref data_type_declarations "type"</em><tt>&gt;(</tt>[<em>list_initializer_args, ...</em>]<tt>)</tt>

    @par Return Type
    - If the type given is a @ref qore_classes "class name" or complex object type with a class name, then this operator returns an object of the specific class given
    - If the type given is a @ref hash_hashdecl_type "hashdecl hash type", then this operator returns a type-safe hash of the given type.
    - If the type given is a @ref hash_complex_type "complex hash type", then this operator returns a hash with type-safe key values of the given type.
    - If the type given is a @ref list_complex_type "complex list type", then this operator returns a list with type-safe element values of the given type.

    @par Examples
    @code{.py}
# create an object
Mutex obj = new Qore::Mutex();

# instantiate a new type-safe hash
hash<MyHash> h1 = new hash<MyHash>();

# instantiate a new hash with type-safe key values
hash<string, int> h2 = new hash<string, int>(("string": 2));

# instantiate a new list with type-safe element values
list<int> l1 = new list<int>(2);
    @endcode

    <b>Arguments Processed by new</b>
    |!Argument|!Processing
    |<em>@ref qore_classes "class_identifier"</em><tt>(</tt>[<em>constructor_args, ...</em>]<tt>)</tt>|The \a class_identifier must be an existing class name or a namespace-prefixed path to an existing class; if so, the operator instantiates an object of this class, executes the constructor for the class (if any exists, along with any base class constructors, if applicable) on the new object, and returns the object (for constructor execution order in an inherited class, see @ref inheritance). If an exception is thrown in the constructor, the object is deleted immediately.
    |<tt>@ref object_type "object"&lt;</tt><em>@ref qore_classes "class_identifier"</em><tt>&gt;(</tt>[<em>constructor_args, ...</em>]<tt>)</tt>|same as above
    |<tt>@ref hash_type "hash"&lt;</tt><em>@ref hashdecl "hashdecl_identifier"</em><tt>&gt;(</tt>[<em>hash_initializer_arg</em>]<tt>)</tt>|The \a hashdecl_identifier must be an existing declared type-safe hash name or a namespace-prefixed path to an existing type-safe hash; if so, the operator instantiates a hash of this type (see @ref hashdecl_creation for more info).
    |<tt>@ref hash_type "hash"&lt;string, </tt><em>@ref data_type_declarations "type"</em><tt>&gt;(</tt>[<em>hash_initializer_arg</em>]<tt>)</tt>|A value of the declared hash with type-safe key values is instantiated and returned
    |<tt>@ref list_type "list"&lt;</tt><em>@ref data_type_declarations "type"</em><tt>&gt;(</tt>[<em>list_initializer_args, ...</em>]<tt>)</tt>|A value of the declared list with type-safe key values is instantiated and returned

    @note
    - When instantiating a class, see the class's documentation for possible exceptions

    @see @ref variable_implicit_construction for a more concise way to declare and initialize variables.

    <hr>
    @subsection background Background Operator (background)

    @par Sandbox Restrictions
    @ref Qore::PO_NO_THREAD_CONTROL

    @par Synopsis
    Start a background thread and return the TID (thread ID).

    @note
    - expressions that have no effect cannot be used with the background operator (a parse exception will be thrown)
    - it is illegal to make changes to a local variable anywhere in a background expression (a parse exception will be thrown)
    - local variables and find expressions are evaluated before the new thread is started and the result of the evaluation is used in the expression in the new thread
    - it is not possible to pass local variables by reference anywhere in a background expression (a parse exception will be thrown)

    @par Syntax
    <tt><b>background</b></tt> <em>@ref expressions "expression"</em>

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} int tid = background startThread();@endcode

    <b>Arguments Processed by background</b>
    |!Argument|!Processing
    |<em>@ref expressions "expression"</em>|The <em>@ref expressions "expression"</em> given as an argument will be executed in a new thread. The TID of the new thread will be returned as the return value of the operator

    @throw THREAD-CREATION-FAILURE If the thread table is full or if the operating system returns an error while starting the thread, this exception is thrown

    <hr>
    @subsection delete Delete Operator (delete)

    @par Synopsis
    The delete operator deletes the contents of an lvalue. If the delete operator is called on an object, the object will be destroyed unconditionally. The delete operator does not return any value.\n\n
    When called on a hash key, the key is removed from the hash entirely; when called on a list element, the element is assigned @ref nothing (i.e. the list size does not change).\n\n
    The delete operator will delete multiple keys from a hash (i.e. delete a slice from a hash) when called on a hash dereferenced by a list of strings, giving the keys to delete (see example below).\n\n
    The delete operator will also remove characters from strings, bytes from binary objects, and elements from lists as well.\n\n
    In the case the delete operator operates on an object, any exception can be thrown that is thrown by the class' destructor.\n\n
    For a similar operator that returns the value that is removed from the data structure, and does not delete objects, see the @ref remove "remove operator".

    @par Syntax
    <tt><b>delete</b></tt> \a lvalue

    @par Return Type
    Does not return any value

    @par Example
    @code{.py}
# delete a single key from a hash
delete value;
# delete multiple values from a hash
delete h.("a", "b", "c");
# delete characters from a string
delete str[1,2,5..7];
# delete bytes from a binary object
delete bin[2..4,10,12];
# delete elements from a list (if any of the referenced list elements are objects, they will be deleted as well)
delete l[2,5..7,8];
    @endcode

    This operator does not throw any exceptions, however exceptions could be thrown in an object's destructor method when deleted by this operator.

    <hr>
    @subsection remove Remove Operator (remove)

    @par Synopsis
    The remove operator removes a value from a data structure, or, in the case the operand of the remove operator is a simple value, the value itself is removed from the variable and returned. The remove operator returns the value removed from the \a lvalue.\n\n
    When called on a hash key, the key is removed from the hash entirely, and the value returned is the value of the key removed from the hash; when called on a list element, the element is assigned @ref nothing (i.e. the list size does not change).\n\n
    The remove operator will remove and return a slice from a hash when called on a hash dereferenced by a list of strings, giving the keys to remove (see example below).\n\n
    The remove operator will also remove characters from strings, bytes from binary objects, and elements from lists as well; when removing invalid or non-existant indices from strings and binary objects, no data is written to the output value, however in the case of a list lvalue, @ref nothing is written to the output list in these cases.  In case the same index is referenced multiple times, the value is repeated in the output value.\n\n
    The remove operator does not call destructors when operating on objects, but if removing an object from an lvalue or from a data structure within the \a lvalue causes the object to go out of scope, it will be destroyed, and then its destructor could throw an exception.\n\n
    For a similar operator that deletes the value that is removed from the data structure, see the @ref delete "delete operator".

    @par Syntax
    <tt><b>remove</b></tt> \a lvalue

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py}
# remove a single value from a hash
auto var = remove hash.value;
# remove a slice from a hash
hash nh = remove h.("a", "b", "c");
# remove a slice from a string
string nstr = remove str[1,2,5..7];
# remove a slice of bytes from a binary object
binary nbin = remove bin[2..4,10,12];
# remove a slice from a list (if any of the referenced list elements are objects, they will be deleted as well)
list nlist = remove l[2,5..7,8];
    @endcode

    This operator does not throw any exceptions, however exception could be thrown in an object's destructor if it goes out of scope due to the action of this operator.

    <hr>
    @subsection cast Cast Operator (cast<>())

    @par Synopsis
    The cast<>() operator provides a way to tell the parser that the type value is not actually the declared type but rather another compatible type as given between the angle brackets.  Parse-time and runtime checks are performed for compatibility.  Casts to @ref hashdecl "hashdecl" types, to the @ref hash_type "hash", and to the @ref list_type "list" types can result in data conversions; see below for more information.

    @par Syntax
    - <tt><b>cast</b>&lt;</tt><em>@ref qore_classes "class_identifier"</em><tt>&gt;(</tt><em>@ref expressions "object_expression"</em><tt>)</tt>
    - <tt><b>cast</b>&lt;@ref object_type "object"&lt;</tt><em>@ref qore_classes "class_identifier"</em><tt>&gt;&gt;(</tt><em>@ref expressions "object_expression"</em><tt>)</tt>
    - <tt><b>cast</b>&lt;@ref hash_type "hash"&lt;</tt><em>@ref hashdecl "hashdecl_identifier"</em><tt>&gt;&gt;(</tt><em>@ref expressions "hash_expression"</em><tt>)</tt>
    - <tt><b>cast</b>&lt;@ref hash_type "hash"&lt;string, </tt><em>@ref data_type_declarations "data_type"</em><tt>&gt;&gt;(</tt><em>@ref expressions "hash_expression"</em><tt>)</tt>
    - <tt><b>cast</b>&lt;@ref hash_type "hash"&gt;(</tt><em>@ref expressions "hash_expression"</em><tt>)</tt>
    - <tt><b>cast</b>&lt;@ref list_type "list"&lt;</tt><em>@ref data_type_declarations "data_type"</em><tt>&gt;&gt;(</tt><em>list_elements, ...</em><tt>)</tt>
    - <tt><b>cast</b>&lt;@ref list_type "list"&gt;(</tt><em>list_elements, ...</em><tt>)</tt>

    @par Return Type
    - If a @ref qore_classes "class name" is given as the target type, then this operator returns an object of the specific class given at runtime.
    - If @ref object_type "object" is given as the target type, the runtime type must be a valid object or a runtime exception will be raised; no conversion is performed on the object.
    - If a @ref hashdecl "type-safe hash" type is given as the target type, then this operator returns a hash of the given type
    at runtime; in this case the hash also undergoes conversion and initialization to the specified type; see
    @ref hashdecl_creation for more information.
    - If a complex type is given as the target type, then this operator will convert the expression's value to the declared type
    at runtime if possible.
    - If @ref hash_type "hash" is given as the target type, the runtime type must be a valid hash or a runtime exception will be raised, additionally, any type-safe information is removed and an untyped hash is returned
    - If @ref list_type "list" is given as the target type, the runtime type must be a valid list or a runtime exception will be raised, additionally, any type-safe information is removed and an untyped list is returned

    @par Data Conversions with <tt>cast<>(...)</tt>
    - <tt><b>cast</b>&lt;@ref hash_type "hash"&lt;</tt><em>@ref hashdecl "hashdecl_identifier"</em><tt>&gt;&gt;(</tt><em>@ref expressions "hash_expression"</em><tt>)</tt>: performs initialization of @ref hashdecl "hashdecl" keys with initializer expressions for keys not present in the output evaluated hash expression
    - <tt><b>cast</b>&lt;@ref hash_type "hash"&gt;(</tt><em>@ref expressions "hash_expression"</em><tt>)</tt>: removes any type-safe information from the output evaluated hash expression
    - <tt><b>cast</b>&lt;@ref list_type "list"&gt;(</tt><em>list_elements, ...</em><tt>)</tt>: removes any type-safe information from the output evaluated list expression

    @par Examples
    @code{.py}
# simple class cast
cast<SubClass>(obj).method();

# cast with complex object type (class cast)
cast<object<SubClass>>(obj).method();

# cast to object; ensures a valid object at runtime
cast<object>(obj);

# hashdecl cast with type conversion
hash<MyType1> h = cast<hash<MyType1>>(h2);

# complex hash cast
hash<string, MyClass>h = cast<hash<string, MyClass>(get_untyped_hash());

# removes key type information from a type-safe hash
any h = cast<hash>(new hash<MyHashdecl>());

# removes element type information from a type-safe list
any l = cast<list>(new list<int>(1));
    @endcode

    <b>Target Type Argument Processed by cast<>()</b>
    |!Argument|!Processing
    |<em>@ref qore_classes "class_identifier"</em>|This must be a literal unquoted string giving a class name or a namespace-qualified path to a class (ex: \c Namespace::MyClass); a runtime check for compatibility with the target class is performed on the evaluated expression
    |<tt>@ref object_type "object"&lt;</tt><em>@ref qore_classes "class_identifier"</em><tt>&gt;</tt>|this is equivalent to <em>@ref qore_classes "class_identifier"</em> alone; a runtime check for compatibility with the target class is performed on the evaluated expression
    |<em>@ref hashdecl "hashdecl_identifier"</em>|This must be a literal unquoted string giving a @ref hashdecl "type-safe hash" name or a namespace-qualified path to a type-safe hash (ex: \c Namespace::MyHash); a runtime check for compatibility with the target @ref hashdecl "hashdecl" is performed on the evaluated expression; any keys missing from the expression that have default initializer expressions in the @ref hashdecl "hashdecl" are initialized accordingly
    |<tt>@ref hash_type "hash"&lt;string, </tt><em>@ref data_type_declarations "data_type"</em><tt>&gt;</tt>|The second type in the type parameter list gives the hash key value type; runtime type compatibility checks are performed but no conversions are made; a runtime exception will be thrown if the evaluated expression does not correspond to the declared type
    |<tt>@ref list_type "list"&lt;</tt><em>@ref data_type_declarations "data_type"</em><tt>&gt;</tt>|The single type in the type parameter list gives the list element value type; runtime type compatibility checks are performed but no conversions are made; a runtime exception will be thrown if the evaluated expression does not correspond to the declared type

    @throw RUNTIME-CAST-ERROR The expression given does not evaluate to a value that can be converted to the given type

    <hr>
    @subsection logical_negation_operator Logical Not Operator (!)

    @par Synopsis
    Reverses the logical sense of an expression (@ref True "True" becomes @ref False "False" and @ref False "False" becomes @ref True "True").

    @par Syntax
    <tt>!</tt><em>expression</em>

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (!exists error_code)
    do_something();
    @endcode

    <b>Arguments Processed by !</b>
    |!Argument|!Processing
    |\a expression|The expression is evaluated and converted to a @ref boolean "bool", if necessary. Then the value is logically reversed (@ref True "True" becomes @ref False "False", @ref False "False" becomes @ref True "True")

    This operator does not throw any exceptions.

    <hr>
    @subsection binary_not_operator Binary Not Operator (~)

    @par Synopsis
    The value of each bit in an integer is reversed (0 becomes 1, 1 becomes 0).

    @par Syntax
    <tt>~</tt><em>@ref expressions "expression"</em>

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a = ~b;@endcode

    <b>Arguments Processed by ~</b>
    |!Argument|!Processing
    |<em>@ref expressions "expression"</em>|The argument is converted to an integer (if necessary), and bitwise negation is performed on the argument (ex: <tt>666 & ~27</tt> results in \c 640)

    This operator does not throw any exceptions

    <hr>
    @subsection unary_minus_operator Unary Minus Operator (-)

    @par Synopsis
    Changes the sign of numeric values.

    @par Syntax
    -expression

    @par Return Type
    @ref int_type "int", @ref number_type "number", @ref float_type "float" or @ref date_type "date"

    @par Example
    @code{.py} a = -b;@endcode

    <b>Arguments Processed by - (unary minus)</b>
    |!Argument|!Processing
    |@ref float|Gives the negative of its argument as a @ref float, ex: <tt>-(-1.1) = 1.1, -(1.1) = -1.1</tt>
    |@ref integer|Gives the negative of its argument as an @ref integer, ex: <tt>-(-1) = 1, -(1) = -1</tt>
    |@ref number|Gives the negative of its argument as a @ref number, ex: <tt>-(-1.1n) = 1.1n, -(1.1n) = -1.1n</tt>
    |@ref date|Gives the negative of its argument as a @ref date, ex: <tt>-(-1s) = 1s, -(1s) = -1s</tt>
    |other|Returns 0

    This operator does not throw any exceptions

    <hr>
    @subsection unary_plus_operator Unary Plus Operator (+)

    @par Synopsis
    Does nothing with numeric values, converts others to 0.

    @par Syntax
    +<em>@ref expressions "expression"</em>

    @par Return Type
    @ref int_type "int", @ref number_type "number", @ref float_type "float" or @ref date_type "date"

    @par Example
    @code{.py} a = +b;@endcode

    <b>Arguments Processed by + (unary minus)</b>
    |!Argument|!Processing
    |@ref float|Gives the value of its argument as a @ref float, ex: <tt>+1.1 = 1.1</tt>
    |@ref integer|Gives the value of its argument as an @ref integer, ex: <tt>+1 = 1</tt>
    |@ref number|Gives the value of its argument as a @ref number, ex: <tt>+1.1n = 1.1n</tt>
    |@ref date|Gives the value of its argument as a @ref date, ex: <tt>+1s = 1s</tt>
    |other|Returns 0

    This operator does not throw any exceptions

    <hr>
    @subsection shift Shift Operator (shift)

    @par Synopsis
    Removes the first element from a list and returns that element.  Throws a parse-time exception
    if the \a lvalue is known not to be a list at parse time, otherwise throws a runtime exception if
    the \a lvalue is not a list if @ref strict-args "%strict-args" is in effect.

    @par Syntax
    <tt><b>shift</b></tt> \a lvalue

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} *string a = shift ARGV;@endcode

    <b>Arguments Processed by shift</b>
    |!Argument|!Processing
    |\a lvalue|Returns the first element of the list, and the list is modified by having the first element removed from the list. If the \a lvalue is an empty list, the operator returns no value (@ref nothing).

    This operator throws an exception if the \a lvalue is not a list.

    <hr>
    @subsection pop Pop Operator (pop)

    @par Synopsis
    Removes the last element from a list and returns that element.  Throws a parse-time exception
    if the \a lvalue is known not to be a list at parse time, otherwise throws a runtime exception if
    the \a lvalue is not a list if @ref strict-args "%strict-args" is in effect.

    @par Syntax
    <tt><b>pop</b></tt> \a lvalue

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} a = pop list;@endcode

    <b>Arguments Processed by pop</b>
    |!Argument|!Processing
    |\a lvalue|Returns the last element of the list, and the list is modified, having the last element removed from the list. If the \a lvalue is an empty list, the operator returns no value (@ref nothing).

    This operator throws an exception if the \a lvalue is not a list.

    <hr>
    @subsection chomp Chomp Operator (chomp)

    @par Synopsis
    Removes the end-of-line marker(s) (\c '\\n' or \c '\\r\\n') from a string, or each string element in a list, or each hash key value in a hash (if the value is a string) and returns the number of characters removed.\n\n
    To perform this operation on a non-lvalue expression, see the chomp() function.

    @par Syntax
    <tt><b>chomp</b></tt><i>lvalue</i>

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} chomp str;@endcode

    <b>Arguments Processed by chomp</b>
    |!Argument|!Processing
    |\a lvalue (@ref string)|Removes any EOL characters from a string and returns the number of characters removed.
    |\a lvalue (@ref list)|Removes any EOL characters from each string element of the list passed and returns the number of characters removed.
    |\a lvalue (@ref hash)|Removes any EOL characters from each hash key's value (where the value is a string) and returns the number of characters removed.

    This operator does not throw any exceptions.

    <hr>
    @subsection trim Trim Operator (trim)

    @par Synopsis
    Removes whitespace characters from the beginning and end of a string, or each string element in a list, or each hash key value in a hash (if the value is a string) and returns the value processed (string, list, or hash).\n\n
    To perform this operation on a non-lvalue expression, see the trim() function.\n\n
    The following whitespace characters are removed from the beginning and end of strings: <tt>' '</tt> (blank spaces), \c '\\n', \c '\\r', \c '\\t', \c '\\v' (vertical tab, ASCII 11), and \c '\\0' (null character).

    @par Syntax
    <tt><b>trim</b></tt> \a lvalue

    @par Return Type
    @ref string_type "string", @ref list_type "list", or @ref hash_type "hash"

    @par Example
    @code{.py} trim str;@endcode

    <b>Arguments Processed by trim</b>
    |!Argument|!Processing
    |\a lvalue (@ref string)|Removes whitespace characters from the beginning and end of a string and returns the value processed.
    |\a lvalue (@ref list)|Removes whitespace characters from the beginning and end of each string element of the list passed and returns the list.
    |\a lvalue (@ref hash)|Removes whitespace characters from the beginning and end of each string value of the hash passed and returns the hash.

    This operator does not throw any exceptions.

    <hr>
    @subsection map Map Operator (map)

    @par Synopsis
    Executes (or maps) an expression on a list and returns the result. An optional select expression can be given to filter elements out from the result list.\n\n
    If the first argument is a single element hash expression using curly brackets, then the @ref hmap "hash variant of the map operator" is used instead.\n\n
    If the second argument (<em>@ref expressions "iterator_expression"</em>) is an object inheriting the @ref Qore::AbstractIterator "AbstractIterator" class, the <b><tt>map</tt></b> operator iterates the object by calling @ref Qore::AbstractIterator::next() "AbstractIterator::next()", and the implicit argument <tt>$1</tt> in the <em>@ref expressions "map_expression"</em> and any optional <em>@ref expressions "select_expression"</em> is the value returned by @ref Qore::AbstractIterator::getValue() "AbstractIterator::getValue()".\n\n
    If the second argument is not a list or an object inheriting @ref Qore::AbstractIterator "AbstractIterator", then <em>@ref expressions "map_expression"</em> is executed on the single value and the result is returned (assuming that any <em>@ref expressions "select_expression"</em> accepts the value).\n\n
    If possible, <em>@ref expressions "iterator_expression"</em> is evaluated using @ref op_functional "lazy functional evaluation".

    @par Return Type
    @ref any_type "any"

    @par Syntax
    <tt><b>map</b></tt> <em>@ref expressions "map_expression"</em><tt>,</tt> <em>@ref expressions "iterator_expression" [, @ref expressions "select_expression"]</em>

    @par Examples
    @code{.py}
# returns (2, 4, 6)
list l = map $1 * 2, (1, 2, 3);
    @endcode
    @code{.py}
# prints out the keys of a hash; one to a line
map printf("%s\n", $1), hash.keyIterator();
    @endcode

    <b>Arguments Processed by map</b>
    |!Argument|!Processing
    |<em>@ref expressions "map_expression"</em>|The expression to map on the list; the implicit argument <tt>$1</tt> represents the current element being processed
    |<em>@ref expressions "iterator_expression"</em>|The data to process; if this is not a list then the <em>@ref expressions "map_expression"</em> is run on the single argument passed, unless the <em>@ref expressions "iterator_expression"</em> is an object inheriting the @ref Qore::AbstractIterator "AbstractIterator" class; in this case the <b><tt>map</tt></b> operator iterates the object by calling @ref Qore::AbstractIterator::next() "AbstractIterator::next()"; if supported, this expression is evaluated using @ref op_functional "lazy functional evaluation"
    |<em>[@ref expressions "select_expression"]</em>|An optional expression than can be used to filter out elements of the list before the <em>@ref expressions "map_expression"</em> is applied; if this expression evaluates to @ref False "False" on an element, then the element will be skipped and the <em>@ref expressions "map_expression"</em> will not be applied on that element.

    This operator does not throw any exceptions (however note that exceptions could be thrown by expressions executed by this operator).

    @see @ref hmap for a variant of this operator that creates and returns a hash rather than a list

    @since %Qore 0.8.6.2 the map operator when used with an @ref Qore::AbstractIterator "AbstractIterator" object instantiates the value returned by @ref Qore::AbstractIterator::getValue() "AbstractIterator::getValue()" instead of the iterator itself

    @note the non-hash version of the <b><tt>map</tt></b> operator supports @ref op_functional "lazy functional evaluation" of itself and also of the <em>@ref expressions "iterator_expression"</em>

    <hr>
    @subsection hmap Hash Map Operator (map)

    @par Synopsis
    This variant of the map operator builds a hash from a list or iterator argument and can be differentiated from the standard list @ref map "map" operator by the use of curly brackets in the initial expression; in this case the hash version of the map operator is used.  This operator executes (or maps) an expression on a list and returns the result in form of a hash. An optional select expression can be given to filter elements out from the result hash.\n\n
    If the first argument is anything other than a single element hash expression using curly brackets, then the @ref map "list variant of the map operator" is used instead.\n\n
    If the third argument (<em>@ref expressions "iterator_expression"</em>) is an object inheriting the @ref Qore::AbstractIterator "AbstractIterator" class, the <b><tt>map</tt></b> operator iterates the object by calling @ref Qore::AbstractIterator::next() "AbstractIterator::next()", and the implicit argument <tt>$1</tt> in the <em>@ref expressions "key_expression"</em> and <em>@ref expressions "value_expression"</em> and any optional <em>@ref expressions "select_expression"</em> is the value returned by @ref Qore::AbstractIterator::getValue() "AbstractIterator::getValue()".\n\n
    If the third argument is not a list or an object inheriting @ref Qore::AbstractIterator "AbstractIterator", then <em>@ref expressions "key_expression"</em> and <em>@ref expressions "value_expression"</em> are executed on the single value and the result is returned as a single element hash (assuming that any <em>@ref expressions "select_expression"</em> accepts the value).\n\n

    @par Return Type
    @ref hash in case of a <em>@ref expressions "iterator_expression"</em> with a value, otherwise @ref nothing

    @par Syntax
    <tt><b>map</b> {</tt><em>@ref expressions "key_expression"</em> <tt>:</tt> <em>@ref expressions "value_expression"</em><tt>},</tt> <em>@ref expressions "iterator_expression" [, @ref expressions "select_expression"]</em>

    @par Examples
    @code{.py}
hash h = map {$1 : $1 * 2}, (1, 2, 3);
# returns: {"1": 2, "2": 4, "3": 6}
    @endcode
    @code{.py}
hash h = map {$1 : $1 * 2}, (1, 2, 3), $1 > 1;
# returns: {"2": 4, "3": 6}
    @endcode

    <b>Arguments Processed by the hash version of map</b>
    |!Argument|!Processing
    |<em>@ref expressions "key_expression"</em>|The expression to map on the list or iterator value which will result in the key for the current hash element; the implicit argument <tt>$1</tt> represents the current element being processed. The result of the expression is converted to a string to be used as the hash key for the current element
    |<em>@ref expressions "value_expression"</em>|The expression to map on the list which will result in the value for the current hash element; the implicit argument <tt>$1</tt> represents the current element being processed
    |<em>@ref expressions "iterator_expression"</em>|The data to process; if this is not a list then the <em>@ref expressions "key_expression"</em> and <em>@ref expressions "value_expression"</em> are run on the single argument passed, unless the <em>@ref expressions "iterator_expression"</em> is an object inheriting the @ref Qore::AbstractIterator "AbstractIterator" class; in this case the <b><tt>map</tt></b> operator iterates the object by calling @ref Qore::AbstractIterator::next() "AbstractIterator::next()"; if supported, this expression is evaluated using @ref op_functional "lazy functional evaluation"
    |<em>[@ref expressions "select_expression"]</em>|An optional expression than can be used to filter out elements of the list before the map expression is applied; if this expression evaluates to @ref False "False" on an element, then the element will be skipped and the <em>@ref expressions "key_expression"</em> and <em>@ref expressions "value_expression"</em> will not be applied on that element.

    This operator does not throw any exceptions (however note that exceptions could be thrown by expressions executed by this operator).

    @see @ref map for a variant of this operator that creates and returns a list

    @since %Qore 0.8.12 this variant of the map operator exists which builds a hash from a list or iterator source

    <hr>
    @subsection foldl Fold Left Operator (foldl)

    @par Synopsis
    Folds an operation on a list from left to right and returns the result. The result of each individual operation is used as the first argument in the foldl expression for the next element in the list. The first operation of the fold is made by executing the fold expression on the first and second elements of the list, from this point onwards, the result of each successive operation is used as the first argument for the next operation, the second argument being the next element in the list.\n\n
    If the second argument (\a iterator_expression) is an object inheriting the @ref Qore::AbstractIterator "AbstractIterator" class, the <b><tt>foldl</tt></b> operator iterates the object by calling @ref Qore::AbstractIterator::next() "AbstractIterator::next()", and the implicit arguments <tt>$1</tt> and <tt>$2</tt> in \a expression are the container values returned by @ref Qore::AbstractBidirectionalIterator::getValue() "AbstractBidirectionalIterator::getValue()".\n\n
    If the \a iterator_expression does not evaluate to a list or an object inheriting @ref Qore::AbstractIterator "AbstractIterator", then the evaluated argument is returned immediately with no processing by the <b><tt>foldl</tt></b> expression.\n\n
    If possible, \a iterator_expression is evaluated using @ref op_functional "lazy functional evaluation".

    @par Syntax
    <tt><b>foldl</b></tt> \a expression, \a iterator_expression

    @par Return Type
    @ref any_type "any"

    @par Examples
    The following returns <tt><b>foldl</b></tt> expression returns \c 5
    @code{.py}
int result = foldl $1 - $2, (10, 4, 1);
    @endcode
    \n The following <tt><b>foldl</b></tt> expression joins a list with \c ", " or returns a single argument (if the second operand is not a list)
    @code{.py}
string str = foldl $1 + ", " + $2, list;
    @endcode

    <b>Arguments Processed by foldl</b>
    |!Argument|!Processing
    |\a expression|The expression to fold on the list; the implicit argument <tt>$1</tt> represents the result of the last operation (or the first element in the list when beginning the fold), and <tt>$2</tt> represents the next element of the list.
    |\a iterator_expression|The list, @ref Qore::AbstractIterator "AbstractIterator" object or other value according to the rules above to process; if possible, this expression is evaluated using @ref op_functional "lazy functional evaluation".

    This operator does not throw any exceptions (however note that exceptions could be thrown by expressions executed by this operator).

    @note the <b><tt>foldl</tt></b> operator supports @ref op_functional "lazy functional evaluation" of the \a iterator_expression

<hr>
    @subsection foldr Fold Right Operator (foldr)

    @par Synopsis
    Folds an operation on a list from right to left and returns the result. The result of each individual operation is used as the first argument in the foldr expression for the next element in the list in reverse order. The first operation of the right fold is made by executing the fold expression on the last and penultimate elements of the list, from this point onwards, the result of each successive operation is used as the first argument for the next operation, the second argument being the next element in the list in reverse order.\n\n
    If the second argument (\a iterator_expression) is an object inheriting the @ref Qore::AbstractBidirectionalIterator "AbstractBidirectionalIterator" class, the <b><tt>foldr</tt></b> operator iterates the object by calling @ref Qore::AbstractBidirectionalIterator::prev() "AbstractBidirectionalIterator::prev()", and the implicit arguments <tt>$1</tt> and <tt>$2</tt> in \a expression are the container values returned by @ref Qore::AbstractBidirectionalIterator::getValue() "AbstractBidirectionalIterator::getValue()".\n\n
    If the \a iterator_expression does not evaluate to a list or an object inheriting @ref Qore::AbstractBidirectionalIterator "AbstractBidirectionalIterator", then the evaluated argument is returned immediately with no processing by the <b><tt>foldr</tt></b> expression.\n\n
    If possible, \a iterator_expression is evaluated using @ref op_functional "lazy functional evaluation".

    @par Syntax
    <tt><b>foldr</b></tt> \a expression, \a iterator_expression

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py}
# returns -13
foldr $1 - $2, (10, 4, 1);
    @endcode

    <b>Arguments Processed by foldr</b>
    |!Argument|!Processing
    |\a expression|The expression to fold on the list; the implicit argument <tt>$1</tt> represents the result of the last operation (or the last element in the list when beginning the fold), and <tt>$2</tt> represents the next element of the list in reverse order.
    |\a iterator_expression|The list, @ref Qore::AbstractIterator "AbstractIterator" object or other value according to the rules above to process; if possible, this expression is evaluated using @ref op_functional "lazy functional evaluation".

    This operator does not throw any exceptions (however note that exceptions could be thrown by expressions executed by this operator).

    @note the <b><tt>foldr</tt></b> operator supports @ref op_functional "lazy functional evaluation" of the \a iterator_expression

    <hr>
    @subsection select Select From List Operator (select)

    @par Synopsis
    Selects elements from a list that meet the given criteria and returns the new list.\n\n
    If the first argument (\a iterator_expression) is an object inheriting the @ref Qore::AbstractIterator "AbstractIterator" class, the <b><tt>select</tt></b> operator iterates the object by calling @ref Qore::AbstractIterator::next() "AbstractIterator::next()", and the implicit argument <tt>$1</tt> in \a expression is the value returned by @ref Qore::AbstractIterator::getValue() "AbstractIterator::getValue()"; in this case the operator always returns a list (which may be empty if \a expression returns @ref False "False" for all elements in the iterator object or if the iterator object is empty), and the value of the object in the list returned is the value returned by @ref Qore::AbstractIterator::getValue() "AbstractIterator::getValue()".\n\n
    If the list expression does not evaluate to a list or an object inheriting @ref Qore::AbstractIterator "AbstractIterator", then the select expression is evaluated using the value of the list expression as an argument, if it evaluates to @ref True "True", then the value is returned, otherwise, no value is returned.\n\n
    If possible, \a expression is evaluated using @ref op_functional "lazy functional evaluation".

    @par Syntax
    <tt><b>select</b></tt> \a iterator_expression, \a expression

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py}
# returns (2, 4, 6)
select (1, 2, 3, 4, 5, 6), !($1 % 2);
    @endcode

    <b>Arguments Processed by select</b>
    |!Argument|!Processing
    |\a iterator_expression|The list to process or an object inheriting @ref Qore::AbstractIterator "AbstractIterator"
    |\a expression|The expression will be evaluated on each element of the list, the implicit argument <tt>$1</tt> represents current element of the list (or the iterator object itself when \a iterator_expression is an object inheriting @ref Qore::AbstractIterator "AbstractIterator"); only if the expression evaluates to @ref True "True" will the element appear in the result list

    This operator does not throw any exceptions (however note that exceptions could be thrown by the expression executed by this operator).

    @since %Qore 0.8.6.2 the map operator when used with an @ref Qore::AbstractIterator "AbstractIterator" object instantiates the value returned by @ref Qore::AbstractIterator::getValue() "AbstractIterator::getValue()" instead of the iterator itself

    @note the <b><tt>select</tt></b> operator supports @ref op_functional "lazy functional evaluation" of itself and also of the \a iterator_expression

    <hr>
    @subsection elements Elements Operator (elements)

    @par Synopsis
    Returns the number of elements in a list, the number of keys in a hash, the number of characters (not bytes) in a string, or the number of bytes in a binary object.

    @par Syntax
    <tt><b>elements</b></tt> \a expression

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} int size = elements list;@endcode

    <b>Arguments Processed by elements</b>
    |!Argument|!Processing
    |\a expression @ref list_type "list"|Returns the number of elements in the list
    |\a expression @ref hash_type "hash"|Returns the number of keys in the hash
    |\a expression @ref string_type "string"|Returns the number of characters in the string (which may be different than the number of bytes for multi-byte character encodings such as \c UTF-8
    |\a expression @ref binary_type "binary"|Returns the number of bytes in the binary object

    This operator does not throw any exceptions.

    @see @ref <value>::size()

    <hr>
    @subsection keys Keys Operator (keys)

    @par Synopsis
    Returns a list representing the keys in a hash.

    @par Syntax
    <tt><b>keys</b></tt> \a hash_expression

    @par Return Type
    @ref list_type "list" or @ref nothing

    @par Example
    @code{.py}
foreach string key in (keys hash)
    printf("%s = %s\n", key, hash{key});
    @endcode

    <b>Arguments Processed by keys</b>
    |!Argument|!Processing
    |\a hash_expression|Returns a list of strings giving the keys in \a hash_expression, which must evaluate to a hash. If not, then no value is returned.

    This operator does not throw any exceptions.

    @see
    - @ref <hash>::keys()
    - @ref <object>::keys()

    <hr>
    @subsection multiplication_operator Multiply Operator (*)

    @par Synopsis
    Multiplies two arguments.

    @par Syntax
    \a expression1 <tt>*</tt> \a expression2

    @par Return Type
    @ref int_type "int", @ref float_type "float", or @ref number_type "number"

    @par Example
    @code{.py} value = x * y;@endcode

    <b>Arguments Processed by * (in order of precedence)</b>
    |!Argument|!Processing
    |@ref number_type "number"|Gives the result of multiplying its arguments; @ref integer "ints" and @ref float "floats" are converted to @ref number "numbers" if at least one of the arguments is a @ref number "number"
    |@ref float_type "float"|Gives the result of multiplying its arguments; @ref integer "ints" are converted to @ref float "floats" if at least one of the arguments is a @ref float "float"
    |@ref int_type "int"|Gives the result of multiplying its arguments
    |any other type|Converts argument to a @ref number "number" and performs the multiplication

    This operator does not throw any exceptions.

    <hr>
    @subsection division_operator Divide Operator (/)

    @par Synopsis
    Divides a number by another.

    @par Syntax
    \a expression1 <tt>/</tt> \a expression2

    @par Return Type
    @ref int_type "int", @ref float_type "float", or @ref number_type "number"

    @par Example
    @code{.py} value = x / y;@endcode

    <b>Arguments Processed by / (in order of precedence)</b>
    |!Argument|!Processing
    |@ref number_type "number"|Gives the result of dividing its arguments; @ref integer "ints" and @ref float "floats" are converted to @ref number "numbers" if at least one of the arguments is a @ref number "number"
    |@ref float_type "float"|Gives the result of dividing its arguments; @ref integer "ints" are converted to @ref float "floats" if at least one of the arguments is a @ref float "float"
    |@ref int_type "int"|Gives the result of dividing its arguments
    |any other type|Converts argument to a @ref float_type "float" and performs the division

    @throw DIVISION-BY-ZERO division by zero error

    <hr>
    @subsection modulo_operator Modulo Operator (%)

    @par Synopsis
    Gives the integer remainder after division of one number by another.

    @par Syntax
    \a expression1 <tt>%</tt> \a expression2

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} mod = x % y;@endcode

    <b>Arguments Processed by %</b>
    |!Argument|!Processing
    |@ref int_type "int"|Gives \a expression1 modulo \a expression2 (ex: <tt>12 % 10</tt> result in \c 2). Arguments are converted to integers if necessary.

    This operator does not throw any exceptions.

    <hr>
    @subsection plus_operator Plus (Addition and Concatenation) Operator (+)

    @par Synopsis
    Numeric addition, list, string, binary, and hash concatenation operator.

    @par Syntax
    \a expression1 <tt>+</tt> \a expression2

    @par Return Type
    @ref int_type "int", @ref float_type "float", @ref number_type "number", @ref date_type "date", @ref list_type "list", @ref string_type "string", @ref binary_type "binary", or @ref hash_type "hash"

    @par Example
    @code{.py} a = 1 + 2;@endcode
    @code{.py} string = "hello" + "-there";@endcode
    @code{.py} list = (1, 2) + ("three", "four", "five");@endcode
    @code{.py} hash = ( "key1" : 1, "key2" : 2) + ( "key3" : "three", "key4": "four");@endcode
    @code{.py} bin = bin1 + bin2;@endcode

    <b>Arguments Processed by + (in order of precedence)</b>
    |!Argument|!Processing
    |@ref list_type list|Gives the result of concatenating its arguments, i.e. <tt>(1, 2) + (3, 4) = (1, 2, 3, 4)</tt>
    |@ref string_type "string"|Gives the result of concatenating its arguments
    |@ref date_type "date"|Gives the result of adding date/time values (see @ref date_time_arithmetic)
    |@ref number_type "number"|Gives the result of adding its arguments
    |@ref float_type "float"|Gives the result of adding its arguments
    |@ref int_type "int"|Gives the result of adding its arguments
    |@ref hash_type "hash"|Gives the result of concatenating/merging its arguments. Any common keys will be overwritten by the values in the second hash (\a expression2)

    This operator does not throw any exceptions.

    <hr>
    @subsection minus_operator Minus Operator (-)

    @par Synopsis
    With @ref float "float", @ref integer "integer", or @ref number "number" arguments, subtracts one number from another.\n\n
    With @ref date "date" arguments, subtracts one date from another; if both date arguments are @ref absolute_dates "absolute dates", the result is a @ref relative_dates "relative date" (duration) giving the time between them; if the first date argument is an @ref absolute_dates "absolute date" and the second is a @ref relative_dates "relative date" (duration), then the result is an @ref absolute_dates "absolute date". If both date arguments are @ref relative_dates "relative dates", then the result is a @ref relative_dates "relative date". If the first argument is a @ref relative_dates "relative date" and the second date is an @ref absolute_dates "absolute date", the @ref absolute_dates "absolute date"'s epoch offset (offset in seconds and microseconds from \c 1970-01-01Z) is used to perform the calculation, and a @ref relative_dates "relative date/time value" is produced.\n\n
    However, if the left-hand side is a @ref hash "hash", and the right-hand side is a string, then the result will be a new hash with the hash key represented by the string removed. If the left-hand side is a hash and the right-hand side is a list, then a new hash will be produced and each element from the list will be converted to a string key and any hash item with a matching key will be deleted from the new hash. Having both left and right arguments hashes is an invalid operation which does not modify the hashes in any way and silently returns @ref nothing.

    @par Syntax
    \a expression1 <tt>-</tt> \a expression2

    @par Return Type
    @ref int_type "int", @ref float_type "float", @ref number_type "number", @ref date_type "date", or @ref hash_type "hash"

    @par Example
    @code{.py} num = x - y;@endcode
    @code{.py} date = 2010-05-13 - P3MT14H10M;@endcode
    @code{.py} hash = hash - "key";@endcode
    @code{.py} hash = hash - ("key1", "key2", "key3");@endcode

    <b>Arguments Processed by - (in order of precedence)</b>
    |!Argument|!Processing
    |@ref date_type "date"|date subtraction: \a expression1 - \a expression2
    |@ref number_type "number"|arithmetic subtraction: \a expression1 - \a expression2
    |@ref float_type "float"|arithmetic subtraction: \a expression1 - \a expression2
    |@ref int_type "int"|arithmetic subtraction: \a expression1 - \a expression2
    |@ref hash_type "hash" - @ref string_type "string"|hash key deletion: \a expression1 - \a expression2
    |@ref hash_type "hash" - @ref list_type "list"|hash key deletion: \a expression1 - \a expression2; all elements of the list are converted to strings (if necessary) and any keys with those names are deleted from the hash.
    |@ref hash_type "hash" - @ref hash_type "hash"|no-op; silently returns @ref nothing

    This operator does not throw any exceptions.

    <hr>
    @subsection shift_right_operator Shift Right Operator (>>)

    @par Synopsis
    Shifts bits in an integer towards zero (divides an integer by a power of 2)

    @par Syntax
    \a expression1 <tt>\>\></tt> \a expression2

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a = x >> y;@endcode

    <b>Arguments Processed by >></b>
    |!Argument|!Processing
    |@ref int_type "int"|Gives the result of shifting \a expression1 right by \a expression2 bits. Arguments are converted to integers if necesssary.

    This operator does not throw any exceptions.

    <hr>
    @subsection shift_left_operator Shift Left Operator (<<)

    @par Synopsis
    Shifts bits in an integer towards infinity (multiplies an integer by a power of 2)

    @par Syntax
    \a expression1 <tt>\<\<</tt> \a expression2

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a = x << y;@endcode

    <b>Arguments Processed by <<</b>
    |!Argument|!Processing
    |@ref int_type "int"|Gives the result of shifting \a expression1 left by \a expression2 bits. Arguments are converted to integers if necessary.

    This operator does not throw any exceptions.

    <hr>
    @subsection instanceof Operator (instanceof)

    @par Synopsis
    Tests if an expression is an instance of the given type or not, meaning that the type can accept the value.

    @par Syntax
    \a expression <tt><b>instanceof</b></tt> \a type_identifier

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (obj instanceof Qore::Mutex)
    print("object is Mutex\n");
    @endcode

    <b>Arguments Processed by instanceof</b>
    |!Argument|!Processing
    |\a expression|If expression is an instance of the named type, which is defined as the type is able to accept the value, then the operator returns @ref True "True", otherwise returns @ref False "False".

    This operator does not throw any exceptions.

    <hr>
    @subsection exists Exists Operator (exists)

    @par Synopsis
    Tests if an expression represents a value or not.

    @par Syntax
    <tt><b>exists</b></tt> \a expression

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (exists a)
    printf("a = n\n", a);
    @endcode

    <b>Arguments Processed by exists</b>
    |!Argument|!Processing
    |\a expression|If \a expression evaluates to a value, then the operator returns @ref True "True", otherwise returns @ref False "False".

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_less_than_operator Less Than Operator (<)

    @par Synopsis
    Tests if a value is less than another; types are converted if necessary (ex: <tt>("1" < 2)</tt> is @ref True "True").

    @par Syntax
    \a expression1 < \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x < y)
    printf("%n is less than %n\n", x, y);
    @endcode

    <b>Arguments Processed by < (in order of precedence)</b>
    |!Argument|!Processing
    |@ref number_type "number"|If \a expression1 is numerically less than \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref float_type "float"|If \a expression1 is numerically less than \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref int_type "int"|If \a expression1 is numerically less than \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref string_type "string"|If \a expression1 comes before \a expression2 in string sort order, returns @ref True "True", otherwise returns @ref False "False"
    |@ref date_type "date"|If \a expression1 is before (or a shorter amount of time than of the arguments are @ref relative_dates) \a expression2, returns @ref True "True", otherwise returns @ref False "False"

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_greater_than_operator Greater Than Operator (>)

    @par Synopsis
    Tests if a value is greater than another; types are converted if necessary (ex: <tt>("2" > 1)</tt> is @ref True "True").

    @par Syntax
    \a expression1 > \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x > y)
    printf("%n is less than %n\n", x, y);
    @endcode

    <b>Arguments Processed by > (in order of precedence)</b>
    |!Argument|!Processing
    |@ref number_type "number"|If \a expression1 is numerically greater than \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref float_type "float"|If \a expression1 is numerically greater than \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref int_type "int"|If \a expression1 is numerically greater than \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref string_type "string"|If \a expression1 comes after \a expression2 in string sort order, returns @ref True "True", otherwise returns @ref False "False"
    |@ref date_type "date"|If \a expression1 is after \a expression2, returns @ref True "True", otherwise returns @ref False "False"

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_equality_operator Equals Operator (==)

    @par Synopsis
    Tests if a value is equal to another; types are converted if necessary (ex: <tt>("1" == 1)</tt> is @ref True "True"). For absolute equals, where types must also be equal to return true, see the @ref logical_absolute_equality_operator.

    @par Syntax
    \a expression1 == \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x == y)
    printf("%n is equal to %n\n", x, y);
    @endcode

    <b>Arguments Processed by == (in order of precedence)</b>
    |!Argument|!Processing
    |@ref string_type "string"|If \a expression1 is equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref number_type "number"|If \a expression1 is equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref float_type "float"|If \a expression1 is equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref int_type "int"|If \a expression1 is equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref date_type "date"|If \a expression1 is equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref list_type "list"|If each element in the each list where order is relevant satisfies this operator, the operator returns @ref True "True", otherwise it returns @ref False "False"
    |@ref hash_type "hash"|If each hash has the same keys and the value of each equal key in each hash satisfies this operator, the operator returns @ref True "True", otherwise it returns @ref False "False"
    |@ref binary_type "binary"|If \a expression1's memory contents and size are equal to \a expression2's, then returns @ref True "True", otherwise @ref False "False"
    |@ref object_type "object"|If \a expression1 is a reference to the same object as \a expression2, then returns @ref True "True", otherwise @ref False "False"
    |@ref null|If both expressions are @ref null, returns @ref True "True", otherwise returns @ref False "False"
    |@ref nothing|If neither expression has a value, returns @ref True "True", otherwise returns @ref False "False"

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_inequality_operator Not Equals Operator (!=)

    @par Synopsis
    Tests if a value is not equal to another; types are converted if necessary (ex: <tt>("1" != 1)</tt> is @ref False "False").

    @par Syntax
    \a expression1 != \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x != y)
    printf("%n is not equal to %n\n", x, y);
    @endcode

    <b>Arguments Processed by != (in order of precedence)</b>
    |!Argument|!Processing
    |@ref string_type "string"|If \a expression1 is not equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref number_type "number"|If \a expression1 is not equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref float_type "float"|If \a expression1 is not equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref int_type "int"|If \a expression1 is not equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref date_type "date"|If \a expression1 is not equal to \a expression2, returns @ref True "True", otherwise @ref False "False"
    |@ref list_type "list"|If each element in the each list where order is relevant satisfies this operator, the operator returns @ref True "True", otherwise it returns @ref False "False"
    |@ref hash_type "hash"|If the hashes have different keys or the value of each equal key in each hash satisfies this operator, the operator returns @ref True "True", otherwise it returns @ref False "False"
    |@ref binary_type "binary"|If \a expression1's memory contents or size are not equal to \a expression2's, then returns @ref True "True", otherwise @ref False "False"
    |@ref object_type "object"|If \a expression1 is not a reference to the same object as \a expression2, then returns @ref True "True", otherwise @ref False "False"
    |@ref null|If either expressions is not @ref null, returns @ref True "True", otherwise returns @ref False "False"
    |@ref nothing|If one of the expressions has a value, returns @ref True "True", otherwise returns @ref False "False"

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_less_than_or_equals_operator Less Than Or Equals Operator (<=)

    @par Synopsis
    Tests if a value is less than or equals to another value; types are converted if necessary (ex: <tt>("1" <= 2)</tt> is @ref True "True").

    @par Syntax
    \a expression1 <= \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x <= y)
    printf("%n is less than or equal to %n\n", x, y);
    @endcode

    <b>Arguments Processed by <= (in order of precedence)</b>
    |!Argument|!Processing
    |@ref number_type "number"|If \a expression1 is numerically less than or equal to \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref float_type "float"|If \a expression1 is numerically less than or equal to \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref int_type "int"|If \a expression1 is numerically less than or equal to \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref string_type "string"|If \a expression1 comes before in string sort order or is the same as \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref date_type "date"|If \a expression1 is before or is the same exact date and time as \a expression2, returns @ref True "True", otherwise returns @ref False "False"

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_greater_than_or_equals_operator Greater Than Or Equals Operator (>=)

    @par Synopsis
    Tests if a value is greater than or equals to another value; types are converted if necessary (ex: <tt>("2" >= 1)</tt> is @ref True "True").

    @par Syntax
    \a expression1 >= \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x >= y)
    printf("%n is greater than or equal to %n\n", x, y);
    @endcode

    <b>Arguments Processed by >= (in order of precedence)</b>
    |!Argument|!Processing
    |@ref number_type "number"|If \a expression1 is numerically greater than or equal to \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref float_type "float"|If \a expression1 is numerically greater than or equal to \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref int_type "int"|If \a expression1 is numerically greater than or equal to \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref string_type "string"|If \a expression1 comes after in string sort order or is the same as \a expression2, returns @ref True "True", otherwise returns @ref False "False"
    |@ref date_type "date"|If \a expression1 is after or is the same exact date and time as \a expression2, returns @ref True "True", otherwise returns @ref False "False"

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_comparison_operator Comparison (<=>) Operator

    @par Synopsis
    Tests if the left-hand value is less than, equal, or greater than the right-hand value; types are converted if necessary (ex: ("1" <=> 2) returns -1).

    @par Syntax
    \a expression1 <=> \a expression2

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py}
switch (x <=> y) {
    case -1:
        print("x is less than y\n");
        break;

    case 0:
        print("x is equal to y\n");
        break;

    case 1:
        print("x is greater than y\n");
        break;
}
    @endcode

    <b>Arguments Processed by <=> (in order of precedence)</b>
    |!Argument|!Processing
    |@ref string_type "string"|If \a expression1 comes after in string sort order as \a expression2, returns \c 1, otherwise if they are equal, returns \c 0, otherwise if \a expression1 comes before \a expression2, returns \c -1
    |@ref number_type "number"|If \a expression1 is numerically greater than \a expression2, returns \c 1, otherwise if they are equal returns \c 0, otherwise returns \c -1
    |@ref float_type "float"|If \a expression1 is numerically greater than \a expression2, returns \c 1, otherwise if they are equal returns \c 0, otherwise returns \c -1
    |@ref int_type "int"|If \a expression1 is numerically greater than \a expression2, returns \c 1, otherwise if they are equal returns \c 0, otherwise returns \c -1
    |@ref date_type "date"|If \a expression1 is after \a expression2, returns \c 1, otherwise if they are equal returns \c 0, otherwise returns \c -1

    This operator throws NAN-COMPARE-ERROR if any of the operands is NaN.

    <hr>
    @subsection logical_absolute_equality_operator Absolute Equals Operator (===)

    @par Synopsis
    Checks two values for equality without doing any data type conversions; if the types do not match, then the result is @ref False "False".

    @par Syntax
    \a expression1 === \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x === y)
    printf("%n is equal to %n and has the same data type as well\n", x, y);
    @endcode

    <b>Arguments Processed by ===</b>
    |!Argument|!Processing
    |All|This operator returns @ref True "True" only if the types and values of both sides of the operator are exactly equal, otherwise returns @ref False "False". No type conversions are done.

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_absolute_inequality_operator Absolute Not Equals Operator (!==)

    @par Synopsis
    Checks two values for inequality without doing any data type conversions. If the data types do not match, then returns @ref True "True".

    @par Syntax
    \a expression1 !== \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x !== y)
    printf("%n is not equal to %n and may not have the data type as well\n", x, y);
    @endcode

    <b>Arguments Processed by !==</b>
    |!Argument|!Processing
    |All|This operator returns @ref True "True" if either the types or the values of the arguments are different, otherwise it retuns @ref False "False". No type conversions are done.

    This operator does not throw any exceptions.

    <hr>
    @subsection regex_match_operator Regular Expression Match Operator (=~)

    @par Synopsis
    Checks for a regular expression match; returns @ref True "True" if the expression matches the string, @ref False "False" if not. See @ref qore_regex_options for the meaning of the \c i, \c s, \c x, and \c m options after the regular expression.\n\n
    See @ref qore_regex for more information about regular expression support in %Qore.

    @par Syntax
    \a expression <tt>=~ [m]/</tt><em>regex</em><tt>/[isxmu]</tt>

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (str =~ /hello/)
    printf("%s contains 'hello'\n", str);
    @endcode

    <b>Arguments Processed by =~</b>
    |!Argument|!Processing
    |@ref string_type "string"|This operator returns @ref True "True" if the regular expression in \a regex matches the string in \a expression.

    This operator does not throw any exceptions.

    <hr>
    @subsection regex_no_match_operator Regular Expression No Match Operator (!~)

    @par Synopsis
    Checks for a regular expression non match; returns @ref True "True" if the expression does not match the string, @ref False "False" if it does. See @ref qore_regex_options for the meaning of the \c i, \c s, \c x, and \c m options after the regular expression.\n\n
    See @ref qore_regex for more information about regular expression support in %Qore.

    @par Syntax
    \a expression <tt>!~ [m]/</tt><em>regex</em><tt>/[isxmu]</tt>

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (str !~ /hello/)
    printf("%s does not contain 'hello'\n", str);
    @endcode

    <b>Arguments Processed by !~</b>
    |!Argument|!Processing
    |@ref string_type "string"|This operator returns @ref True "True" if the regular expression in \a regex does not match the string in \a expression.

    This operator does not throw any exceptions.

    <hr>
    @subsection regex_subst_operator Regular Expression Substitution Operator

    @par Synopsis
    Looks for a regular expression match in a string, and, if found, substitutes the matched string with a new string. Subpattern backreferences are supported in the target string, <tt>$1</tt>=first subpattern, <tt>$2</tt>=second subpattern, etc... See @ref qore_regex_options for the meaning of the \c i, \c s, \c x, and \c m options after the regular expression.\n\n
    See @ref qore_regex for more information about regular expression support in %Qore.

    @par Syntax
    \a lvalue <tt>=~ s/</tt><em>regex_pattern</em><tt>/</tt><em>target_string</em><tt>/[isxmug]</tt>

    @par Return Type
    @ref string_type "string" or @ref nothing (if the \a lvalue does not hold a string)

    @par Example
    @code{.py}
str =~ s/hello/goodbye/i;
str =~ s/(\w+) +(\w+)/$2, $1/;
    @endcode

    <b>Arguments Processed by =~ s///</b>
    |!Argument|!Processing
    |@ref string_type "string"|This operator substitutes text in the \a lvalue string if the regular expression matches. Subpattern backreferences are supported in \a target_string, <tt>$1</tt>=first subpattern, <tt>$2</tt>=second subpattern, etc..

    This operator does not throw any exceptions.

    <hr>
    @subsection regex_extract_operator Regular Expression Pattern Extraction Operator

    @par Synopsis
    Matches regular expression patterns (enclosed in parentheses) in a string and returns a list giving the text matched for each pattern. If the regular expression does not match, then no value (@ref nothing) is returned. See @ref qore_regex_options for the meaning of the \c i, \c s, \c x, and \c m options after the regular expression.\n\n
    See @ref qore_regex for more information about regular expression support in %Qore.

    @par Syntax
    \a string <tt>=~ x/</tt><em>regex_with_patterns</em><tt>/[isxmug]</tt>

    @par Return Type
    @ref list_type "list" or @ref nothing (if the \a lvalue does not hold a string or if the pattern is not matched)

    @par Example
    @code{.py}
list =~ x/(\w+):(\w+)/;
list =~ x/(.*)\.(.*)/;
    @endcode

    <b>Arguments Processed by =~ x//</b>
    |!Argument|!Processing
    |@ref string_type "string"|This operator extracts strings from \a string based on patterns enclosed in parentheses in the regular expression.

    This operator does not throw any exceptions.

    <hr>
    @subsection transliteration_operator Transliteration Operator

    @par Synopsis
    Makes character substitutions in an lvalue; character ranges can also be used.

    @par Syntax
    \a lvalue <tt>=~ tr/</tt><em>source_chars</em><tt>/</tt><em>target_chars</em><tt>/</tt>

    @par Return Type
    @ref string_type "string" or @ref nothing (if the \a lvalue does not hold a string)

    @par Example
    @code{.py} str =~ tr/a-z/A-Z/;@endcode

    <b>Arguments Processed by =~ tr//</b>
    |!Argument|!Processing
    |@ref string_type "string"|This operator substitutes characters in the \a lvalue string. Note that if there are more characters in \a source_chars than in \a target_chars, then the last character in \a target_chars will be used for any source matches where the source character position is greater than the length of \a target_chars.

    This operator does not throw any exceptions.

    <hr>
    @subsection bitwise_and_operator Bitwise/Binary And Operator (&)

    @par Synopsis
    Performs a bitwise (binary) AND operation on two integers.

    @par Syntax
    \a expression1 & \a expression2

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a = x & y;@endcode

    <b>Arguments Processed by &</b>
    |!Argument|!Processing
    |@ref int_type "int"|Gives the result of the binary (bitwise) AND operation between \a expression1 and \a expression2 (ex: <tt>0xffb2 & 0xa1 = 0xa1</tt>); operands are converted to integers if necessary.

    This operator does not throw any exceptions.

    <hr>
    @subsection bitwise_or_operator Bitwise/Binary Or Operator (|)

    @par Synopsis
    Performs a bitwise (binary) OR operation on two integers.

    @par Syntax
    \a expression1 | \a expression2

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a = x | y;@endcode

    <b>Arguments Processed by |</b>
    |!Argument|!Processing
    |@ref int_type "int"|Gives the result of the binary (bitwise) OR operation between \a expression1 and \a expression2 (ex: <tt>0xb001 \| 0xfea = 0xbfeb</tt>); operands are converted to integers if necessary

    This operator does not throw any exceptions.

    <hr>
    @subsection bitwise_xor_operator Bitwise/Binary Xor Operator (^)

    @par Synopsis
    Performs a bitwise (binary) XOR operation on two integers.

    @par Syntax
    \a expression1 ^ \a expression2

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a = x ^ y;@endcode

    <b>Arguments Processed by ^</b>
    |!Argument|!Processing
    |@ref int_type "int"|Gives the result of the binary (bitwise) EXCLUSIVE OR operation between \a expression1 and \a expression2 (ex: <tt>0xaef1 & 0xfb32 = 0x55c3</tt>); operands are converted to integers if necessary

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_and_operator Logical And Operator (&&)

    @par Synopsis
    Checks to see if two expressions are @ref True "True" with logical short-circuiting.

    @par Syntax
    \a expression1 && \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x && y)
    printf("%n and %n are both True\n", x, y);
    @endcode

    <b>Arguments Processed by &&</b>
    |!Argument|!Processing
    |@ref bool_type "bool"|Returns @ref True "True" if both expressions are @ref True "True", @ref False "False" if otherwise. Logical short-circuiting is implemented; if \a expression1 is @ref False "False", then \a expression2 is not evaluated, and the operator returns @ref False "False".

    This operator does not throw any exceptions.

    <hr>
    @subsection logical_or_operator Logical Or Operator (||)

    @par Synopsis
    Returns @ref True "True" if either of the arguments are @ref True "True" with logical short-circuiting.

    @par Syntax
    \a expression1 || \a expression2

    @par Return Type
    @ref bool_type "bool"

    @par Example
    @code{.py}
if (x || y)
    printf("either %n or %n or both are True\n", x, y);
    @endcode

    <b>Arguments Processed by ||</b>
    |!Argument|!Processing
    |@ref bool_type "bool"|Returns @ref True "True" if either or both expressions evaluate to @ref True "True", @ref False "False" if otherwise. Logical short-circuiting is implemented; if \a expression1 is @ref True "True", then \a expression2 is not evaluated, and the operator returns @ref True "True".

    This operator does not throw any exceptions.

    <hr>
    @subsection conditional_operator Conditional Operator (? :)

    @par Synopsis
    Evaluates and returns the value of one of two expressions depending on the value of a conditional expression.

    @par Syntax
    \a expression ? \a if_true_expression : \a if_false_expression

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} a = (z > 100 ? "Big" : "Small");@endcode

    <b>Arguments Processed by ? :</b>
    |!Argument|!Processing
    |All|If \a expression is evaluated to be @ref True "True", then the \a if_true_expression is evaluated and returned. Otherwise the \a if_false_expression is evaluated and returned.

    This operator does not throw any exceptions.

    <hr>
    @subsection null_coalescing_operator Null Coalescing Operator (??)

    @par Synopsis
    Evaluates the first operand and checks for a value (i. e. not @ref nothing or @ref null).  If it evaluates to a value, then the value of the first operand is returned, otherwise the second operand is evaluated and returned.  When chained, the first argument with a value is returned.

    @par Syntax
    \a expression1 ?? \a expression2

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} x = a ?? b ?? c;@endcode

    <b>Arguments Processed by ??</b>
    |!Argument|!Processing
    |All|If \a expression1 is evaluated to be @ref nothing or @ref null then the \a expession2 is evaluated and returned. Otherwise the value of \a expression1 is returned.

    This operator does not throw any exceptions.

    See also @ref value_coalescing_operator that works same except for operands are evaluated based on being @ref False "False" instead of being @ref nothing or @ref null.


    <hr>
    @subsection value_coalescing_operator Value Coalescing Operator (?*)

    @par Synopsis
    Evaluates the first operand and checks for a value (@ref True "True" or @ref False "False"). If it evaluates to @ref True "True", then the value of the first operand is returned, otherwise the second operand is evaluated and returned.  When chained, the first argument with a value is returned.

    @par Syntax
    \a expression1 ?* \a expression2

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} x = a ?* b ?* c;@endcode

    <b>Arguments Processed by ?*</b>
    |!Argument|!Processing
    |All|If \a expression1 is evaluated to be @ref False "False" then the \a expession2 is evaluated and returned. Otherwise the value of \a expression1 is returned.

    This operator does not throw any exceptions.

    See also @ref null_coalescing_operator that works same except for operands are evaluated based on being @ref nothing or @ref null instead of being @ref False "False".


    <hr>
    @subsection comma_operator Comma Operator (,)

    @par Synopsis
    Makes a list from more than one element.

    @par Syntax
    \a expression1, \a expression2

    @par Return Type
    @ref list_type "list"

    @par Example
    @code{.py} a = 1, 2, "three";@endcode

    <b>Arguments Processed by ,</b>
    |!Argument|!Processing
    |All|The comma operator builds lists of arguments

    This operator does not throw any exceptions.

    <hr>
    @subsection unshift Unshift Operator (unshift)

    @par Synopsis
    Inserts an element into the first position of a list, moves all other elements up one position and returns the list processed. Throws an exception if the \a lvalue is not a list.

    @par Syntax
    <tt><b>unshift</b></tt> \a lvalue, \a expression

    @par Return Type
    @ref list_type "list"

    @par Example
    @code{.py} unshift list, "one";@endcode

    <b>Arguments Processed by unshift</b>
    |!Argument|!Processing
    |All|Inserts the value of \a expression as the first element in the list given by \a lvalue. All other elements in the list are moved forward. If \a expression evaluates to a list, this list will be appended as the last element of \a lvalue. To concatenate lists, use the @ref plus_operator "plus operator".

    <hr>
    @subsection push Push Operator (push)

    @par Synopsis
    Adds one element to the end of a list and returns the list processed. Throws a parse-time exception
    if the \a lvalue is known not to be a list at parse time, otherwise throws a runtime exception if
    the \a lvalue is not a list if @ref strict-args "%strict-args" is in effect.

    @par Syntax
    <tt><b>push</b></tt> \a lvalue, \a expression

    @par Return Type
    @ref list_type "list"

    @par Example
    @code{.py} push list, "last";@endcode

    <b>Arguments Processed by push</b>
    |!Argument|!Processing
    |All|Appends the value of the \a expression as the last element in the list given by \a lvalue. If \a expression evaluates to a list, this list will be appended as the last element of \a lvalue. To concatenate lists, use the @ref plus_operator "plus operator".

    <hr>
    @subsection splice Splice Operator (splice)

    @par Synopsis
    Removes and optionally inserts elements in lists, strings, and binary objects and returns the \a lvalue after processing. For a similar operator that returns the values removed, see the @ref extract "extract operator".\n\n
    Works on strings, lists, and binary data in a similar way; removes elements from a list, characters from a string, or bytes from binary data and optionally inserts new ones. If no \a length_expression is given, splice removes all elements/characters/bytes from the list, string, or binary data lvalue starting at \a offset_expression (offsets begin at 0). Otherwise, a number of elements/characters/bytes equal to \a length_expression is removed (or up to the end of the list/string/data if applicable). If \a substitution_expression is present, then the removed elements/characters/bytes are substituted with the elements/string/bytes given by this expression.\n\n
    Note that string splice takes character offsets, which may not be the same as byte offsets for multi-byte character encodings, such as \c UTF-8

    @par Syntax
    <tt><b>splice</b></tt> \a lvalue, \a offset_expression<em>, [length_expression, [substitution_expression]]</em>

    @par Return Type
    @ref list_type "list", @ref string_type "string", or @ref binary_type "binary" (returns \a lvalue after processing)

    @par Example
    @code{.py} splice list, 2, 2;@endcode
    @code{.py} splice string, 2, 2, "-text-";@endcode
    @code{.py} splice bin, 2, 2, <deadbeef>;@endcode

    <b>Arguments Processed by splice</b>
    |!Argument|!Processing
    |\a lvalue (@ref list_type "list", @ref string_type "string", or @ref binary_type "binary")|If the \a lvalue is a list, list elements are processed, if it is a string, characters in the string are processed, and for binary data, bytes are processed. For any other data type, no action is taken.
    |\a offset_expression|The start element/character/byte position for removing elements/characters/bytes from the list, string, or binary data; if this value is negative, it gives the element offset from the end of the data
    |\a length_expression|The number of elements/characters/bytes to remove. If this expression is not present, then all elements/characters/bytes from the offset to the end of the list/string/binary data are removed. If this expression is present and evaluates to 0, no characters/elements/byte are removed; if this value is negative, then it gives an offset from the end of the data (ie -2 means remove all elements/characters/bytes up to but not including the last two)
    |\a substitution_expression|For list splice, an optional element or list to substitute for the removed elements (to insert a list in a single element's position, make sure that the list to be inserted is the first and only element of another list used as the argument in this position; in other words, pass a list within a single-element list). For string splice, an optional string to substitute for the removed characters.  For binary splice, string or binary data to substitute for any removed bytes.

    <hr>
    @subsection extract Extract Operator (extract)

    @par Synopsis
    Removes and optionally inserts elements in lists and strings. For a similar operator that removes values from an lvalue and returns the \a lvalue (instead of the value removed), see the @ref splice "splice operator".\n\n
    Works on either strings, lists, and binary data in a similar way; removes elements from a list, characters from a string, and bytes from binary data and optionally inserts new ones. If no length_expression is given, extract removes all elements/characters/bytes from the \a lvalue starting at \a offset_expression (offsets begin at 0). Otherwise, a number of elements/characters/bytes equal to \a length_expression is removed (or up to the end of the data if applicable). If \a substitution_expression is present, then the removed elements/characters/bytes are substituted with the data given by this expression.\n\n
    When operating on lists, a list is returned of any elements extracted (if no elements are extracted, then an empty list is returned); when operating on strings, a string is extracted of all characters extracted from the string (if no characters are extracted, then an empty string is returned).  When operating on binary data, a binary object is returned.\n\n
    Note that string extract takes character offsets, which may not be the same as byte offsets for multi-byte character encodings, such as \c UTF-8

    @par Syntax
    <tt><b>extract</b></tt> \a lvalue, \a offset_expression<em>, [length_expression, [substitution_expression]]</em>

    @par Return Type
    @ref list_type "list", @ref string_type "string", or @ref binary_type "binary" (the value(s) removed from \a lvalue)

    @par Example
    @code{.py} list sublist = extract list, 2, 2;@endcode
    @code{.py} string substring = extract string, 2, 2, "-text-";@endcode
    @code{.py} binary b = extract bin, 2, 2, <deadbeef>;@endcode

    <b>Arguments Processed by extract</b>
    |!Argument|!Processing
    |\a lvalue (@ref list_type "list", @ref string_type "string", or @ref binary_type "binary")|If the \a lvalue is a list, list elements are processed, if it is a string, characters in the string are processed, and for binary data, bytes are processed. For any other data type, no action is taken.
    |\a offset_expression|The start element/character/byte position for removing elements/characters/bytes from the list, string, or binary data; if this value is negative, it gives the element offset from the end of the data
    |\a length_expression|The number of elements/characters/bytes to remove. If this expression is not present, then all elements/characters/bytes from the offset to the end of the list/string/binary data are removed. If this expression is present and evaluates to 0, no characters/elements/byte are removed; if this value is negative, then it gives an offset from the end of the data (ie -2 means remove all elements/characters/bytes up to but not including the last two)
    |\a substitution_expression|For list extract, an optional element or list to substitute for the removed elements (to insert a list in a single element's position, make sure that the list to be inserted is the first and only element of another list used as the argument in this position; in other words, pass a list within a single-element list). For string splice, an optional string to substitute for the removed characters.  For binary splice, string or binary data to substitute for any removed bytes.

    <hr>
    @subsection assignment_operator Assignment Operator (=)

    @par Synopsis
    Assigns a value to an lvalue and returns the value assigned.

    @par Syntax
    \a lvalue <tt>=</tt> \a expression

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py} a = 1;@endcode

    <b>Arguments Processed by =</b>
    |!Argument|!Processing
    |All|Assigns the value of \a expression to \a lvalue

    <hr>
    @subsection weak_assignment_operator Weak Reference Assignment Operator (:=)

    @par Synopsis
    Identical to the @ref assignment_operator "assignment operator" except when the rvalue is an object;
    in such cases a weak reference to the object is assigned instead of a strong reference.  Weak references
    do not extend the life of an object and also do not participate in object graph cycles (i.e. recursive
    references) and therefore can be used to break up large graphs of objects to improve garbage collector
    performance with such graphs, however the programmer must ensure that the object has a valid
    strong reference elsewhere or the object will go out of scope.\n\n
    This operator should only be used in very special circumstances by
    expert users and is only allowed when the @ref allow-weak-references "%allow-weak-references" sandbox
    permission is set.

    @par Syntax
    \a lvalue <tt>:=</tt> <em>@ref expressions "rvalue_expression"</em>

    @par Return Type
    @ref any_type "any"

    @par Example
    @code{.py}object a := get_object_from_cache();@endcode

    <b>Arguments Processed by :=</b>
    |!Argument|!Processing
    |All|Assigns the value of \a expression to \a lvalue and returns the value assigned; if <em>@ref expressions "rvalue_expression"</em> is an object, a weak reference is assigned instead of a strong reference

    <hr>
    @subsection plus_equals_operator Plus Equals Operator (+=)

    @par Synopsis
    Increments and concatenates an lvalue with the value of an expression depending on the data type of the \a lvalue, unless the \a lvalue is @ref nothing, in which case this operator acts like the assignment operator (simply assigns the value of the right hand side to the \a lvalue).

    @par Syntax
    \a lvalue <tt>+=</tt> \a expression

    @par Return Type
    @ref int_type "int", @ref float_type "float", @ref number_type "number", @ref date_type "date", @ref list_type "list", @ref string_type "string", @ref binary_type "binary", @ref hash_type "hash", or @ref object_type "object"

    @par Example
    @code{.py} a += 10;@endcode
    @code{.py} date += P1M2DT45M;@endcode
    @code{.py} list += new_element;@endcode
    @code{.py} string += ".foo";@endcode
    @code{.py} binary += <0c67a374>@endcode
    @code{.py} hash += ("new-key" : 1, "other" : "two");@endcode
    @code{.py} object += hash;@endcode

    <b>Arguments Processed by +=</b>
    |!Argument|!Processing
    |\a lvalue (@ref list_type "list")|the expression will be evaluated and concatenated to the \a lvalue. If \a expression is a list, the lists will be concatenated, to ensure adding a single element to a list, use the @ref push "push operator"
    |\a lvalue (@ref hash_type "hash" or (@ref object_type "object")|the \a expression will be evaluated, and, if it is a hash or object, then it's members will be added to the \a lvalue, any duplicate elements in the \a lvalue will be overridden by elements in the \a expression.
    |\a lvalue (@ref string_type "string")|the \a expression will be evaluated and converted to a string if necessary and concatenated to the \a lvalue.
    |\a lvalue (@ref number_type "number")|the \a expression will be evaluated and converted to a number if necessary and added to the \a lvalue.
    |\a lvalue (@ref float_type "float")|the \a expression will be evaluated and converted to a float if necessary and added to the \a lvalue.
    |\a lvalue (@ref binary_type "binary")|the \a expression will be evaluated and converted to a binary if necessary and added to the \a lvalue.
    |\a lvalue (@ref date_type "date")|the \a expression will be evaluated and converted to a date if necessary and added to the \a lvalue.
    |\a lvalue (@ref nothing)|the \a lvalue will be assigned to the value of \a expression.
    |\a lvalue (all other types)|the \a lvalue's type will be converted to an integer, and the \a expression will be evaluated and converted to an integer if necessary, and then the result will be added to the \a lvalue.

    <hr>
    @subsection minus_equals_operator Minus Equals Operator (-=)

    @par Synopsis
    For a float or integer argument, decrements the value of an \a lvalue by the value of an \a expression. However if the \a lvalue is a hash or object and the \a expression is a string, removes the key represented by the string from the hash or object.

    @par Syntax
    \a lvalue <tt>-=</tt> \a expression

    @par Return Type
    @ref int_type "int", @ref float_type "float", @ref number_type "number", @ref date_type "date", @ref hash_type "hash", or @ref object_type "object"

    @par Example
    @code{.py} a -= 10;@endcode
    @code{.py} date -= PT45H213S;@endcode
    @code{.py} hash -= "key";@endcode
    @code{.py} hash -= ("key1", "key2");@endcode
    @code{.py} object -= "key";@endcode
    @code{.py} object -= list_of_keys;@endcode

    <b>Arguments Processed by -=</b>
    |!Argument|!Processing
    |\a lvalue (@ref number_type "number")|the \a expression will be evaluated and converted to a number if necessary and subtracted from the \a lvalue
    |\a lvalue (@ref float_type "float")|the \a expression will be evaluated and converted to a float if necessary and subtracted from the \a lvalue
    |\a lvalue (@ref date_type "date")|the \a expression will be evaluated and converted to a date if necessary and subtracted from the \a lvalue
    |\a lvalue (@ref hash_type "hash" or (@ref object_type "object"), \a expression (@ref string_type "string")|the hash key represented by \a expression will be removed from the \a lvalue
    |\a lvalue (@ref hash_type "hash" or (@ref object_type "object"), \a expression (@ref list_type "list")|each element in the list will be converted to a string (if necessary) and the key represented by each string will be removed from the hash or object
    |\a lvalue (@ref nothing), \a expression (any type)|the \a expression will be assigned to \a lvalue
    |\a lvalue (all other types)|the \a lvalue's type will be converted to an integer (if necessary), and the \a expression will be evaluated and converted to an integer (if necessary), and then the result will be subtracted from the \a lvalue

    <hr>
    @subsection and_equals_operator And Equals Operator (&=)

    @par Synopsis
    Performs a bitwise (binary) AND operation on an \a lvalue using the value of an \a expression and returns the new value.

    @par Syntax
    \a lvalue <tt>&=</tt> \a expression

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a &= 0xfe;@endcode

    <b>Arguments Processed by &=</b>
    |!Argument|!Processing
    |All|the \a lvalue's type will be converted to an integer if necessary, and the \a expression will be evaluated and converted to an integer as well if necessary, and then the result will be binary and'ed to the \a lvalue

    <hr>
    @subsection or_equals_operator Or Equals Operator (|=)

    @par Synopsis
    Performs a bitwise (binary) OR operation on an \a lvalue using the value of an \a expression and returns the new value.

    @par Syntax
    \a lvalue <tt>|=</tt> \a expression

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a |= 0xba;@endcode

    <b>Arguments Processed by |=</b>
    |!Argument|!Processing
    |All|the \a lvalue's type will be converted to an integer if necessary, and the \a expression will be evaluated and converted to an integer as well if necessary, and then the result will be binary or'ed to the \a lvalue

    <hr>
    @subsection modulo_equals_operator Modulo Equals Operator (%=)

    @par Synopsis
    Performs a modulo calculation on an lvalue using the value of an expression and returns the new value.

    @par Syntax
    \a lvalue <tt>%=</tt> \a expression

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a %= 100;@endcode

    <b>Arguments Processed by %=</b>
    |!Argument|!Processing
    |All|the \a lvalue's type will be converted to an integer if necessary, and the \a expression will be evaluated and converted to an integer as well if necessary, and then the result will be used to divide the \a lvalue's value and the remainder will be saved to the \a lvalue

    <hr>
    @subsection multiply_equals_operator Multiply Equals Operator (*=)

    @par Synopsis
    Performs a multiplication operation on an lvalue using the value of an expression and returns the value assigned.

    @par Syntax
    \a lvalue <tt>*=</tt> \a expression

    @par Return Type
    @ref int_type "int", @ref float_type "float", or @ref number_type "number"

    @par Example
    @code{.py} a *= 10;@endcode

    <b>Arguments Processed by *=</b>
    |!Argument|!Processing
    |All|The type precedence from highest to lowest is @ref number "number", @ref float "float" float, and @ref integer "int", other types are converted to @ref integer "int". The \a expression will be evaluated and multiplied by the \a lvalue, and the result will be saved to the \a lvalue.

    <hr>
    @subsection divide_equals_operator Divide Equals Operator (/=)

    @par Synopsis
    Performs a division operation on an lvalue using the value of an expression and returns the value assigned.

    @par Syntax
    \a lvalue <tt>/=</tt> \a expression

    @par Return Type
    @ref int_type "int", @ref float_type "float", or @ref number_type "number"

    @par Example
    @code{.py} a /= 10;@endcode

    <b>Arguments Processed by /=</b>
    |!Argument|!Processing
    |All|The type precedence from highest to lowest is @ref number "number", @ref float "float" float, and @ref integer "int", other types are converted to @ref integer "int"; The \a expression will be evaluated and multiplied by the \a lvalue, and the result will be saved to the \a lvalue. The \a expression will be evaluated and used to divide the \a lvalue, and the result will be saved to the \a lvalue.

    @throw DIVISION-BY-ZERO If the divisor expression evaluates to zero, this exception is thrown

    <hr>
    @subsection xor_equals_operator Xor Equals Operator (^=)

    @par Synopsis
    Performs an exclusive-or operation on an lvalue using the value of an expression.

    @par Syntax
    \a lvalue <tt>^=</tt> \a expression

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a ^= 0xf9034ba7;@endcode

    <b>Arguments Processed by ^=</b>
    |!Argument|!Processing
    |All|Values are converted to integers if necessary. The \a expression will be evaluated and exclusive-or'ed with the \a lvalue, and the result will be saved to the \a lvalue

    <hr>
    @subsection shift_left_equals_operator Shift Left Equals Operator (\<\<=)

    @par Synopsis
    Performs a shift-left operation on an lvalue using the value of an expression and returns the value assigned.

    @par Syntax
    \a lvalue <tt>\<\<=</tt> \a expression

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a <<= 3;@endcode

    <b>Arguments Processed by \<\<=</b>
    |!Argument|!Processing
    |All|Values are converted to integers if necessary. The \a expression will be evaluated and this value will determine how many bits the \a lvalue will be shifted left. The result will be saved to the \a lvalue.

    <hr>
    @subsection shift_right_equals_operator Shift Right Equals Operator (\>\>=)

    @par Synopsis
    Performs a shift-right operation on an lvalue using the value of an expression and returns the value assigned.

    @par Syntax
    \a lvalue <tt>\>\>=</tt> \a expression

    @par Return Type
    @ref int_type "int"

    @par Example
    @code{.py} a >>= 3;@endcode

    <b>Arguments Processed by >>=</b>
    |!Argument|!Processing
    |All|Values are converted to integers if necessary. The \a expression will be evaluated and this value will determine how many bits the \a lvalue will be shifted right. The result will be saved to the \a lvalue.

    <hr>
    @subsection range_operator Range Operator (..)

    @par Synopsis
    Returns a list of integers between two expressions.

    @par Syntax
    \a expression1 .. \a expression2

    @par Return Type
    @ref list_type "list"

    @par Example
    @code{.py}
        list = 3..7;
        list = 7..3;
    @endcode

    <b>Arguments Processed by ..</b>
    |!Argument|!Processing
    |@ref int_type "int"|Arguments are converted to integers if necessary.

    @since %Qore 0.8.13

    @note
    - the <b><tt>range</tt></b> operator supports @ref op_functional "lazy functional evaluation" of itself
    - this operator cannot be used on the left-hand side of an assignment expression
*/
