# Sequence Operations

Equivalent functions exist to apply all of the relational, logical and arithmetic operators described above, as well as the math routines described in Library Routines, to entire sequences as well as to single numbers (atoms).
The sq_uminus() function applies the unary (one operand) minus operator to each element of a sequence to yield a sequence of results of the same length. If one of these elements is itself a sequence then the same rule is applied again recursively. e.g.

        x = sq_uminus({1, 2, 3, {4, 5}}) -- x is {-1, -2, -3, {-4, -5}}

If a binary (two-operand) operator function is passed two sequences then they must be of the same length. The binary operation is then applied to corresponding elements taken from the two sequences to get a sequence of results, with the function applied recursively if required. e.g.

        x = sq_add({5, 6, 7, {8, 9}}, {10, 20, 30, {40, 50}}) -- x is {15, 26, 37, {48, 59}}

If a binary operator function is passed one sequence while the other parameter is a single number (atom) then the single number is effectively repeated to form a sequence of equal length to the sequence operand. The rules for operating on two sequences then apply. Should both parameters be atom then it behaves as an infix operator. Some examples:

        x = sq_add({5, 6, 7, {8, 9}}, {10, 20, 30, 40})     -- x is {15, 26, 37, {48, 49}}
        x = sq_add({5, 6, 7, {8, 9}}, 10)                   -- x is {15, 16, 17, {18, 19}}

        x = {1, 2, 3}
        y = {4, 5, 6}
        w = sq_mul(5,y)                     -- w is {20, 25, 30}
        z = sq_add(x,y)                        -- z is {5, 7, 9}
        z = sq_lt(x,y)                         -- z is {1, 1, 1}
        w = {{1, 2}, {3, 4}, {5}}
        w = sq_mul(w,y)         -- w is {{4, 8}, {15, 20}, {30}}

        w = sq_and({1, 0, 0, 1},{1, 1, 1, 0})    -- {1, 0, 0, 0}
        w = sq_not({1, 5, -2, 0, 0})     -- w is {0, 0, 0, 1, 1}
        w = sq_eq({1, 2, 3},{1, 2, 4})   -- w is {1, 1, 0}
        w = ({1, 2, 3} = {1, 2, 4})      -- w is 0 (a singular false)
        w = sq_add(1,2)                  -- w is 3 (just like 1 + 2)

The functions listed below accept either sequence or atom argument(s), unlike the "sq_"-less functions and infix operators which only accept atoms (apart from the first two columns, however those infix operators/sq-less functions always yield a single boolean result). You can find their actual implementations in builtins\psqop.e, which is automatically included when needed.

sq_eq | sq_int | sq_add | sq_and | sq_and_bits | sq_cos | sq_rmdr | sq_abs
sq_ne | sq_atom | sq_sub | sq_not | sq_or_bits | sq_sin | sq_mod | sq_sign
sq_lt | sq_str | sq_mul | sq_or | sq_xor_bits | sq_tan | sq_rand | sq_uminus
sq_le | sq_seq | sq_div | sq_xor | sq_not_bits | sq_arccos | sq_log[10/2] | sq_round
sq_gt |  | sq_floor |  | sq_odd | sq_arcsin | sq_power | sq_ceil
sq_ge | sq_cmp | sq_floor_div |  | sq_even | sq_arctan | sq_sqrt | sq_trunc

Compatibility Notes | Euphoria allows implicit sequence ops whereas Phix requires explicit (functional style) sequence ops. The simple choice is between infix sequence ops and infix comparison operators; try to have both and the syntax collapses and/or becomes ambiguous, for example, assuming you need a boolean result, does the inner comparison in a condition such as (tag="lx")=(flags="rw") reduce to equal(false,false)[T] or equal({1,0},{0,1})[F]? It depends on how you treat the outer two "=": as sequence operators, or as equality operators. Both interpretations could be perfectly reasonable, which would result in an ambiguous and therefore fundamentally broken programming language. In Euphoria you can write {1,2,3}+5, which tends to generate a compile time warning or runtime error in Phix, however you cannot write conditions such as name="pete" and name1<name2 but must instead use equal(name,"pete") and compare(name1,name2)<0, whereas all four forms are perfectly valid in Phix. Analysis of existing source code revealed that comparison was far more common than infix sequence maths, the latter averaging at just once per ten thousand lines of code(!). Apart from upper/lower, which were horribly slow (on Euphoria) anyway, I found no other uses of infix sequence relational ops, anywhere. Hence the design decision was made that Phix would allow infix comparison ops but require (the explicit) sq_add({1,2,3},5) instead of (the implicit) {1,2,3}+5. I fully accept that some_long_variable_name = sq_add(some_long_variable_name,1) is less elegant than some_long_variable_name += 1, but I am just going to say "yes, but you don't need equal() and compare() absolutely ****** everywhere!" The Phix compiler does a pretty reasonable job of identifying implicit infix operators that ought to be explicit (function style) and issues "warning: sequence op (sq_xxx) assumed" messages. Particularly when working with legacy Euphoria code, as you modify it to get rid of such warnings you should take the opportunity to look nearby for any that the compiler might have missed. pwa/p2js: JavaScript is similar to Phix in respect of atom-only operators, for instance the JavaScript expression `[1,2,3]-[4,5,6]` yields NaN. Under "with js", desktop/Phix issues fatal errors rather than substituting the appropriate sq_xxx() function and that way forces the code to be manually corrected, whereas p2js.exw itself just emits gibberish JavaScript for any code that has not been so corrected, but of course perfectly working code for any that has. The automatically transpiled file pwa\builtins\psqop.js is automatically linked in if and only when needed.