.. index:: operators

.. _operators:

=========
Operators
=========

.. Started: August 2016
.. Modified: 2019-10-25/03:06-0400 btiffin
.. Copyright 2016-2017 Brian Tiffin
.. GPL 3.0+ :ref:`license`
.. This file is part of the Unicon Programming documentation

.. image:: images/unicon.png
   :align: center

.. only:: html

    :ref:`genindex`
    :floatright:`<a href="http://unicon.sourceforge.net/">Unicon</a>`

Unicon operators
================

Unicon is an operator rich programming language, very rich.  As Unicon is also
an *everything is an* :ref:`expression <expression>` *language*, operators can
be chained to provide very concise computational phrases.  With the small
price of requiring developers to understand the rules of :ref:`precedence` and
order of operations.

Precedence chart
----------------

.. include:: includes/precedence.inc

Unary operators
===============

.. index:: !!

.. _op\!:

! (generate elements)
---------------------
Generate elements.

! |x| : any*

Generate elements of |x|.  Values produced depends on :ref:`type` of |x|.

For |x| of

========================== ===========================================
Type                       ! produces
========================== ===========================================
:ref:`integer <integer>`   equivalent to ``(1 to x)`` for integer x
:ref:`real <real>`         digits from the real number (including .) 
:ref:`string <string>`     one character substrings of string in order
:ref:`file <file>`         lines/records of resource
:ref:`list <list>`         elements of list
:ref:`record <record>`     field values of record
:ref:`set <set>`           elements of set, in undefined order
:ref:`table <table>`       values of table, in undefined order
:ref:`variable <variable>` fields that can be used for assignment
========================== ===========================================

For :ref:`record` and :ref:`table`, use :ref:`key` to retrieve the key fields,
*which can be used directly to get at the values*.

.. literalinclude:: examples/generate-elements.icn
   :language: unicon
   :start-after: ##+

.. only:: html

    .. rst-class:: rightalign

        :download:`examples/generate-elements.icn`

.. program-output:: unicon -s generate-elements.icn -x
   :cwd: examples

Note that ``!"abc"`` produced ``"a", "b", "c"``, while ``!s`` produced ``s[1],
s[2], s[3]``, which can be assigned to, as can the element references of a
:ref:`list` variable (or other structured) type.  The generate elements
operator doesn't just generate values, it generates the references to the
values if applicable to the surrounding expression and the source, |x|.

.. note:: 

    There may be times when multi-threading changes the state of |x| during
    generation, and it will be up the programmer to account for these times.

--------


.. index:: *

.. _op*:

\* (size)
---------

Size of operator. \*\ |expr| Returns the size of the |expr|.

\*\ |x| : *integer*


- integer, size of the value coerced to string
- real, size of the value coerces to string
- string, number of characters in string
- cset, number of characters in cset
- structure, number of elements in list, set, table, fields of record
- co-expression, number of activations since last reset
- thread, messages in in-box

.. literalinclude:: examples/size-operator.icn
   :language: unicon
   :start-after: ##+

.. only:: html

    .. rst-class:: rightalign

        :download:`examples/size-operator.icn`

.. program-output:: unicon -s size-operator.icn -x
   :cwd: examples


--------


.. index:: +

.. _op+:

\+ (numeric identity)
---------------------

Numeric identity, does not change the value other than to convert to a
required numeric type.

+\ |x| is |x| as a number if possible.

+"123" returns integer 123, +"abc" raises a run-time conversion error.

.. literalinclude:: examples/numeric-identity.icn
   :language: unicon
   :start-after: ##+

.. only:: html

    .. rst-class:: rightalign

        :download:`examples/numeric-identity.icn`

.. program-output:: unicon -s numeric-identity.icn -x
   :cwd: examples
   :returncode: 1

--------


.. index:: -

.. _op-:

\- (negate)
-----------

Negate. Reverses the sign of the given operand.

-\ |x| is the signed reverse of |x| as a number if possible.

-"-123" returns integer 123. ---1 is -1.  -"abc" raises a run-time conversion
error.

.. literalinclude:: examples/negate-operator.icn
   :language: unicon
   :start-after: ##+

.. only:: html

    .. rst-class:: rightalign

        :download:`examples/negate-operator.icn`

.. program-output:: unicon -s negate-operator.icn -x
   :cwd: examples

--------


.. index:: /

.. _/:

/ (null test)
-------------
Null test.

/\ |x| : |x| or &fail

Test |expr| for null.  Succeeds and returns |x| if |x| is null.

This doesn't just return the value :ref:`&null`, but a reference to the
expression if appropriate, which can be set to a value.  This is very useful
for optional arguments and optional default values.

.. sourcecode:: unicon

    /var := "abc"

The null test operator will succeed and produce a reference to ``var`` if it
is :ref:`&null`, and the surrounding assignment can then set a new value.  If
``var`` is already set, the null test will fail and the assignment operation
is not attempted. That is not the only use for the null test operator, but it
the most common.

--------


.. index:: \

.. _\\:

\\ (not null test)
------------------
Not null test.

\\ |x| : |x| or &fail

Test |expr| for nonnull.  Succeeds and returns |x| if |x| is not null.

A handy operator when dealing with possibly unset values.

.. sourcecode:: unicon

    L |||:= [\var]

The nonnull test will return ``var``, unless it is :ref:`&null` in which case
the operator fails.  Only values that have been set will be appended to the
:ref:`list` ``L`` in the expression shown above.

--------


.. index:: .

.. _\.:

\. (dereference)
----------------
Dereference.

\. |x| : |x|

The dereference operator.  It returns the value |x|.

Unless required by context, Unicon will pass references to variables (so they
can be set to new values). The dereference operator returns the actual value
of |x| even if the surrounding context may prefer a reference.

--------


.. index:: =

.. _=expr:

\= (anchored or tab match)
--------------------------
Tab match or anchored pattern match.  Historically this unary operator has
been called tab-match. *Even though it is extended for use with Unicon pattern
types with different semantics, and not just string scanning, it will likely
always be spoken as tab-match.*

=\ |x| : *string* | *pattern*

Equivalent to ``tab(match(s))`` for string *s*, or anchors a pattern match
when |x| is a pattern, ``=p``.

.. literalinclude:: examples/tabmatch-operator.icn
   :language: unicon
   :start-after: ##+

.. only:: html

    .. rst-class:: rightalign

        :download:`examples/tabmatch-operator.icn`

.. program-output:: unicon -s tabmatch-operator.icn -x
   :cwd: examples

--------


.. index:: |

.. _\|:

\| (repeated alternation)
-------------------------
Repeated generation.

\| |x| : |x|\ ``*``

The repeated alternation operator. ``|x`` generates results from evaluating
the expression |x| over and over again, in an infinite loop.

--------


.. index:: ?

.. _op?:

\? (random element)
-------------------
Random element.

Returns a random element from |x|.

- Number, returns a number from 0 to n - 1.
- String, returns a random single character subscript of *s*.
- List, returns a random element from the list.
- Table, returns a random value from the table - not the key.

.. todo:: fill out all the random element types.

--------


.. index:: @

.. _op@:

\@ (activation)
---------------
Activate co-expression. Shown here as a unary operator, but it is actually a
binary operator with an optional initial transmitted value.

When used in a unary prefix mode the default value :ref:`&null` is supplied to
the co-expression.

--------


.. index:: ~

.. _~:

~ (cset complement)
-------------------
cset complement.

~\ |x| returns the cset consisting of all the characters not found in |x|.

Unicon csets include byte values from 0 to 255, and the complement will be
limited to that range.

Other :ref:`set` data cannot really use a complement operator, as that would
result in an unbounded infinite set.

.. literalinclude:: examples/complement-operator.icn
   :language: unicon
   :start-after: ##+

.. only:: html

    .. rst-class:: rightalign

        :download:`examples/complement-operator.icn`

.. program-output:: unicon -s complement-operator.icn -x
   :cwd: examples

--------


Binary Operators
================
Unicon includes a rich set of binary operators, and many can be augmented with
assignment, making for a lengthy list of operator symbols.

.. note::

   In terms of precedence rules, augmented assignment operators are
   equal in precedence to assignment, not the level of precedence for the
   operator being augmented.

   For instance: ``a *:= b + c`` parses as ``a := a * (b + c)``

   The source expression: ``a := a * b + c`` parses as ``a := (a * b) + c``
   
Some few binary operators have optional left hand side parameters, and those
are also included in the Unary Operator list above for completeness
(co-expression activation for instance).


.. index:: &

.. _binop&:

& (conjunction)
---------------
Conjunction.  |x1| & |x2| produces |x2| if |x1| succeeds.

--------

.. index:: &:=

.. _binop&\:=:

&:= (augmented &)
-----------------
Augmented conjunction.  |x1| &:= |x2| produces |x2| if |x1| succeeds and
assigns the result to |x1|. If |x1| fails, no reassignment occurs.

--------


.. index:: |

.. _binop|:

\| (alternation)
----------------
Alternation.  |x1| | |x2| yields the result of |x1| followed by |x2|, in that
order. The alternation operator is a generator.

--------


.. index:: ||

.. _binop||:

\|\| (concatenation)
--------------------
Concatenation.  |x| || |y| produces a new value that is the concatenation of
the strings (or patterns) |x| and |y|.

--------

 
.. index:: ||:=

.. _binop||\:=:

\|\|:= (augmented \|\|)
-----------------------
Augmented concatenation.  |x| || |y| produces a new value that is the
concatenation of the strings (or patterns) |x| and |y|, and assigns the result
to |x|.

--------


.. index:: |||

.. _|||:

\|\|\| (list concatenation)
---------------------------
List concatenation operator.

--------

.. index:: |||:=

.. _|||\:=:

\|\|\|:= (augmented \|\|\|)
---------------------------
Augmented list concatenation operator.

--------


.. index:: ?

.. _binop?:

? (string scan)
---------------
One of the key features of Unicon.  |x1| ? |x2| invokes the string scanner.
The expression |x1| is the :ref:`&subject` and |x2| can be arbitrarily
complex.  See :ref:`string scanning`.

--------


.. index:: ?:=

.. _binop?\:=:

?:= (augmented ?)
-----------------
Augmented string scanning.  The result of the scan is assigned to |x1|.

--------


.. index:: ??

.. _binop??:

?? (pattern scan)
-----------------

Pattern scan operator.  Similar to string scanning, but |expr| is a
:ref:`pattern` not a general Unicon expression.

--------


.. index:: idioms

.. _idioms:

Operator idioms
===============
The chaining capabilities inherent in the nature of Unicon expressions can 
lead to some very powerful programming techniques.  Some of these techniques
are common practise and become idioms, some are yet to be discovered and
some few are just curiosities best left alone as they may be more confusing 
than separating the expression for the sake of clarity.

The order of operations :ref:`precedence` rules can play a large role when
building up expression chains.

For example, string scanning has a lower precedence than assignment:

.. sourcecode:: unicon

    result := subject ? {
        step1()
        step2()
    }

In the code above, ``result`` is set to the original contents of ``subject``,
not the actual result produced by the scanning environment.

The above is equivalent to:

.. sourcecode:: unicon

    (result := subject) ? {
        step1()
        step2()
    }

To get the scanning result, a rather odd looking order of operations control
ends up as:

.. sourcecode:: unicon

    result := (subject ? {
        step1()
        step2()
    })

The idiomatic Unicon expression uses augmented assignment:

.. sourcecode:: unicon

    subject ?:= {
        step1()
        step2()
    }

With the downside that ``subject`` (the data referenced by the variable name
used) is changed after scanning.  Another option is to place the scan inside a
procedure and use

.. sourcecode:: unicon

    suspend subject ? {
        step1()
        step2()
    }

Or, get used to seeing parenthesis control around these often times rather
complex operations.  You will see the ``r := (s ? {code})`` form relatively
frequently in :ref:`IPL` listings. 


.. todo:: more examples and clarification required.  


--------

.. index:: operator functions

.. _opfunc:

Operator functions
==================
Almost all Unicon operators can be used as function call expressions.

A few examples, summing a list of arguments and demonstrating the right hand
side value given a condition test, along with some straight up arithmetic.

.. literalinclude:: examples/opfuncs.icn
   :language: unicon
   :start-after: ##+

.. only:: html

    .. rst-class:: rightalign

        :download:`examples/opfuncs.icn`

.. command-output:: unicon -s opfuncs.icn -x
   :cwd: examples


.. only:: html

   ..

   --------

   :ref:`genindex` | Previous: :doc:`expressions` | Next: :doc:`reserved`

   |