.. 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` |