# Ranges

## Defining a Range​

Use a range in SenseTalk to indicate a range of values. A range is specified by giving a start value and an end value, using either a double-dot operator (two periods in a row, `..`) or the word `to` between the two values.

Syntax:
{from} startValue [ to | .. ] endValue { [{step{ping}} {down} by | step] stepvalue }

Example:

``put 1 to 100 into firstHundredset validRange to 100..200``

A range may optionally include a step value, using the word `by` or `step` or `step by` (the use of step values is described in "Using a Range to Generate a List", below):

Example:

``put 1 to 99 step by 2 into oddNumbersset evenNumbers to 0..100 by 2``

### Simple Uses of Ranges​

In its simplest uses, a range specifies two values. Access the `start` and `end` values directly, as properties of the range:

Example:

``set myRange to 10 .. 20 -- 10 to 20put myRange.start --> 10put myRange's end --> 20add 15 to the end of myRangeput myRange --> 10 to 35``

Use the `is within` operator to test if another value falls within the range:

Example:

``set myRange to 10 .. 20put 13 is within myRange --> Trueput 18.975 is within myRange --> Trueput 9.2 is within myRange --> False``

A range is inclusive, that is, it includes both the start and end values. So any value between 10 and 20, including the values 10 and 20, falls within the example range:

Example:

``set myRange to 10 .. 20put 10 is within myRange --> Trueput 20 is within myRange --> True``

Use the `is a range` operator to test if a value is a range:

Example:

``put myRange is a range --> True``

## Using a Range to Generate a List​

Use a range as a sequence generator to automatically generate a sequence or list of values beginning with the start value of the range and continuing until its end value. The simplest way to cause a range to generate its values is to use the range in a context where a list is expected:

Example:

``put item 5 of 10 to 20 --> 14put the last 3 items of 100..200 by 2 --> [196,198,200]``

If you specify a step by increment for the range, its absolute (positive) value is used when generating a sequence as the increment between sequential items in the list. If you do not specify a step by increment for the range, a value of 1 is assumed. Access or change the increment value of a range by using the `step` property of the range:

Example:

``set the step of myRange to 3``

To generate all of the values in the range at once, use the `as list` operator to request it as a list:

Example:

``put 10.. 20 as a list --> [10,11,12,13,14,15,16,17,18,19,20]put 10 to 20 by 2 as list --> [10,12,14,16,18,20]``

Specify a range's endpoints in either order. For example as a range from 10 to 20 or from 20 to 10. For purposes of the `is within` operator the two are equivalent. The difference is the order in which values are generated if the range is treated as a list or used as an iterator.

Example:

``put 20 .. 10 by 2 as a list --> [20,18,16,14,12,10]``

## Using the `contains` and `is in` Operators with Ranges​

The `contains` and `is in` operators, when used with a range, treat the range as a list. In this case, a range only contains a value if that value is one of the distinct values generated by the range.

note

The `is in` and `is within` operators behave quite differently in this way:

``set range to 10..20put range contains 13 --> Trueput range contains 13.5 --> Falseput 13.5 is within range --> True  (13.5 is between 10 and 20)put 13.5 is in range --> False  (it's not one of the values 10,11,12,13,14,15,16,17,18,19, or 20)``

## Date/Time Ranges​

A date or time range works similarly to a numeric range. Both the start and end values must be valid as date or time values for it to be recognized as a time range:

Example:

``set Q1 to "Jan 1" to "Mar 31"put "Feb 3" is in Q1 --> True``

When a time range is created without explicitly giving a step increment, the step value is assumed to be 1 day, 1 minute, or 1 second, depending on the start and end values:

• If the start and end values are a day apart or more, a step value of 1 day is used.
• If they are within 24 hours of each other but more than a minute apart, a step value of 1 minute will be used,
• if the range is 60 seconds or less a step value of 1 second will be used.

For more natural readability of date/time ranges, specify the step value as a plural time unit like "days" instead of "1 day" or "minutes" instead of "1 minute":

Example:

``set MondaysIn2009 to "2009-01-05" to "2009-12-31" by weeks``

When a date/time range is accessed as a list, each value produced is a date/time value using the same format as the start value.

Example:

``put item 33 of "Jan 1" to "March 31" --> "Feb 2"put item 33 of "January 1" to "Mar 31" --> "February 2"``

## Character Ranges​

A range can also specify a range of Unicode characters. One common use of character ranges is to specify the alphabet:

Example:

``set alphabet to "a".."z"set upperAndLowerLetters to "A".."Z" &&& "a".."z"put "z" to "t" as list --> ["z","y","x","w","v","u","t"]``

## Using a Range as a Chunk Index​

A range can be used to select certain characters, words, items, or other parts of a value:

Example:

``put chars 1..5 of "abcdefgh" --> "abcde"put chars 1..5 by 2 of "abcdefgh" --> "ace"put items 2..6 by 2 of "a,b,c,d,e,f,g,h" --> "b,d,f"put items 2..6 by 2 of [a,b,c,d,e,f,g,h] --> [b,d,f]put chars 8..1 of "abcdefgh" --> "hgfedcba"put chars 8..1 as list of "abcdefgh" --> [h,g,f,e,d,c,b,a]``