A **range** is a dense list of integers, such that the difference between
consecutive elements is a nonzero constant. Ranges can be abbreviated
with the syntactic construct `[ `

or, if the
difference between consecutive elements is 1, as `first`, `second` .. `last` ]`[ `

.
`first` .. `last` ]

If

, `first` `last``[`

is the empty list,
which by definition is also a range. If `first`,`second`..`last`]`first` = `last`,
`[`

is a singleton list, which is a range too.
Note that `first`,`second`..`last`]

must be divisible by the increment `last` - `first`

, otherwise an error is signalled.
`second`
- `first`

Note that a range is just a special case of a list. So everything that
is possible for lists (see Lists) is also possible for ranges. Thus
you can access elements in such a range (see List Elements), test for
membership (see In), etc. You can even assign to such a range (see
List Assignment). Of course, unless you assign

to the entry `last` +
`second`-`first`

, the
resulting list will no longer be a range.
`range`[Length(`range`)+1]

Most often ranges are used in connection with the `for`

-loop (see For).
Here the construct

`for `

replaces the `var` in [`first`..`last`] do `statements` od

`for `

, which is more
usual in other programming languages.
`var` from `first` to `last` do `statements` od

Note that a range is at the same time also a set (see Sets), because it contains no holes or duplicates and is sorted, and also a vector (see Vectors), because it contains no holes and all elements are integers.

gap> r := [10..20]; [ 10 .. 20 ] gap> Length( r ); 11 gap> r[3]; 12 gap> 17 in r; true gap> r[12] := 25;; r; [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25 ] gap> r := [1,3..17]; [ 1, 3 .. 17 ] gap> Length( r ); 9 gap> r[4]; 7 gap> r := [0,-1..-9]; [ 0, -1 .. -9 ] gap> r[5]; -4 gap> r := [ 1, 4 .. 32 ]; Error, Range: <high>-<low> must be divisible by <inc> gap> s := [];; for i in [10..20] do Add( s, i^2 ); od; s; [ 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400 ]

The first section in this chapter describes the function that tests if a list is a range (see IsRange).

The other section tells you more about the internal representation of ranges (see More about Ranges).

`IsRange( `

`obj` )

`IsRange`

returns `true`

if `obj`, which may be an object of any type, is
a range and `false`

otherwise. A range is a list without holes such that
the elements are integers with a constant increment. Will cause an error
if `obj` is an unassigned variable.

gap> IsRange( [1,2,3] ); true # this list is a range gap> IsRange( [7,5,3,1] ); true # this list is a range gap> IsRange( [1,2,4,5] ); false # this list is a set and a vector, but not a range gap> IsRange( [1,,3,,5,,7] ); false # this list contains holes gap> IsRange( 1 ); false # is not even a list gap> IsRange( [] ); true # the empty list is a range by definition gap> IsRange( [1] ); true # singleton lists are a range by definition too

For some lists the kernel knows that they are in fact ranges. Those
lists are represented internally in a compact way instead of the ordinary
way. This is important since this representation needs only 12 bytes for
the entire list while the ordinary representation needs *4 length* bytes.

Note that a list that is represented in the ordinary way might still be a
range. It is just that **GAP** does not know this. This section tells
you under which circumstances a range is represented in the compact way,
so you can write your program in such a way that you make best use of
this compact representation for ranges.

Lists created by the syntactic construct `[ `

are of course known to be ranges and are represented in the compact
way.
`first`, `second` .. `last`
]

If you call `IsRange`

for a list represented the ordinary way that is
indeed a range, `IsRange`

will note this, change the representation from
the ordinary to the compact representation, and then return `true`

;

If you change a range that is represented in the compact way, by
assignment, `Add`

or `Append`

, the range will be converted to the
ordinary representation, even if the change is such that the resulting
list is still a proper range.

Suppose you have built a proper range in such a way that it is
represented in the ordinary way and that you now want to convert it to
the compact representation to save space. Then you should call `IsRange`

with that list as an argument. If it is indeed a proper range, `IsRange`

will convert it to the compact representation. You can think of the call
to `IsRange`

as a hint to **GAP** that this list is a proper range.

GAP 3.4.4

April 1997