### Sequences 3

### Subscripting

A single element of a sequence may be selected by giving the element number in square brackets. Element numbers start at `1`. Non-integer subscripts are truncated down to an integer.

For example, if `x` contains `{5, 7.2, 9, 0.5, 13}` then `x[2]` is `7.2`. Suppose we assign something different to `x[2]`:

x = {5, 7.2, 9, 0.5, 13} x[2] = {11,22,33} ? x -- {5, {11,22,33}, 9, 0.5, 13}

Then `x` becomes: `{5, {11,22,33}, 9, 0.5, 13}`. Now if we ask for `x[2]` we get `{11,22,33}` and if we ask for `x[2][3]` we get the `atom` 33.

If you try to subscript with a number that is outside of the range `1` to the number of elements, you will get a **subscript error**. For example `x[0]`, `x[-99]` or `x[6]` will cause errors. So will `x[1][3]` since `x[1]` is not a sequence. There is no limit to the number of subscripts that may follow a variable, but the variable must contain sequences that are nested deeply enough.

In algebra, the *matrix*, is a common two dimensional collection of values. Mathematicians use them often to organize calculations. The *array* is a special data-type invented to allow matrix-like arrangements of data, and is a feature of many languages. Euphoria does not need a special data-type, it can use the sequence to represent an array or matrix:

x = { {5, 6, 7, 8, 9}, -- x[1] {1, 2, 3, 4, 5}, -- x[2] {0, 1, 0, 1, 0} -- x[3] }

where we have written the numbers in a way that makes the structure clearer. An expression of the form `x[i][j]` can be used to access any element.

The two dimensions are not symmetric however, since an entire "row" can be selected with x[i], but you need to use vslice() in the Standard Library to select an entire column.

Other logical structures, such as n-dimensional arrays, arrays of strings, structures, arrays of structures, ..., can all be represented by sequences:

3-D array:

y = { {{1,1}, {3,3}, {5,5}}, {{0,0}, {0,1}, {9,1}}, {{-1,9},{1,1}, {2,2}} } -- y[2][3][1] is 9

Array of strings:

s = {"Hello", "World", "Euphoria", "", "Last One"} -- s[3] is "Euphoria" -- s[3][1] is 'E'

A Structure:

employee = { {"John","Smith"}, 45000, 27, 185.5 }

To access "fields" or elements within a structure it is good programming style to make up an `enum` that names the various fields. This will make your program easier to read. For the example above you might have:

enum NAME, FIRST_NAME=1, LAST_NAME, SALARY=2, AGE, WEIGHT employees = { {{"John","Smith"}, 45000, 27, 185.5}, -- a[1] {{"Bill","Jones"}, 57000, 48, 177.2}, -- a[2] -- .... etc. } -- employees[2][SALARY] would be 57000.

Note that expressions in general may not be subscripted, just variables. For example: `{5+2,6-1,7*8,8+1}[3]` is *not* supported, nor is something like: `date()[MONTH]`. You have to assign the sequence returned by `date`() to a variable, then subscript the variable to get the month.

### Euphoria data structures are almost infinitely flexible

Arrays in many languages are constrained to have a fixed number of elements, and those elements must all be of the same type. Euphoria eliminates both of those restrictions by defining all "arrays" (by using Euphoria sequences) as a list of zero or more Euphoria objects whose element count can be changed at any time.

You can easily add a new structure to the employee sequence above, or store an unusually long name in the NAME field and Euphoria will take care of it for you. If you wish, you can store a variety of different employee "structures", with different sizes, all in one sequence. However, when you retrieve a sequence element, it is not guaranteed to be of any type. You, as a programmer, need to check that the retrieved data is of the type you'd expect, Euphoria will not. The only thing it will check is whether an assignment is legal. For example, if you try to assign a sequence to an integer variable, Euphoria will complain at the time your code does the assignment.

Not only can a Euphoria program represent all conventional data structures but you can create very useful, flexible structures that would be hard to declare in many other languages.

One of the interesting things thats happens when you program in Euphoria is that it is no longer necessary to think in terms of specific data-types. Instead just arrange data in a convenient way that makes sense. The sequence can be used for any collection of values. These sequences are dynamic and can change length and shape. Indexing and operations on sequences always work the same way. This is why we describe Euphoria as simple and powerful.

### Last Element $

The `length()` built-in function will tell you how many elements are in a sequence. So the last element of a sequence `s`, is:

s[length(s)]

A short-hand for this is:

s[$]

Similarly,

s[length(s)-1]

can be simplified to:

s[$-1]

The `$` may only appear between square braces and it equals the length of the sequence that is being subscripted. Where there's nesting, e.g.:

s[$ - t[$-1] + 1]

The first `$` above refers to the length of `s`, while the second `$` refers to the length of `t` (as you'd probably expect). An example where `$` can save a lot of typing, make your code clearer, and probably even faster is:

longname[$][$] -- last element of the last element

Compare that with the equivalent:

longname[length(longname)][length(longname[length(longname)])]