# Narrowing a range

[Narrowing](../narrowing.md) › range. The names in the examples are those of [section 2](../narrowing.md#2-the-names-in-the-examples).

A `range` alternative is `{:range, endpoint}`, where `endpoint` is a union: `range<number>`. A range **value** is a `Feel.Value.Range` (D-61), made by a literal such as `[1..10)` or a prefix test used as a value such as `(< 10)`. It has no value set of its own: the type does not say which endpoints a range has. So a fact about a range can say only whether it is `null`, what its endpoint type is, and what shape it has when it is compared with another range.

## A range value in a name

| Condition | `r` when true | `r` when not true |
| --- | --- | --- |
| `r = null` | `Null` | `range<number \| Null>` |
| `r != null` | `range<number \| Null>` | `Null` |
| `r instance of range<number>` | `range<number \| Null>` | `Null` |
| `r instance of range<string>` | `range<Null>` | `range<number \| Null> except range<string \| Null> \| Null` |

`range<number>` is a range whose endpoints are numbers or `null`; `range<Null>` is a range of nothing but `null` endpoints, which is also a `range<string>`. Equality of two ranges is read as the equality of two lists is: part by part (D-194), against a type that is known.

| Condition | `v` when true | `v` when not true |
| --- | --- | --- |
| `v instance of range<number>` | `range<number \| Null>` | `Any except range<number \| Null> \| Null` |

## A range in an `in` is not a range value

`x in [1..10]` is **not** a test against a range value. A range written in an `in`, or in a list of unary tests, is the two comparisons it says: `x >= 1 and x <= 10`, with the open and closed ends as written (D-61, D-194). That is why it narrows `x` exactly ([number](number.md#between-and-in)), while a range held in a *name* does not: the test cannot be read until run time, and a test that is a value rather than a comparison says nothing.

| Condition | `x` when true | `x` when not true |
| --- | --- | --- |
| `x in [1..10]` | `number in [1..10]` | `number in [-max..1), (10..max] \| Null` |
| `x in r` | `number \| Null` | `number \| Null` |

The built-ins that relate a point and a range (`includes(r, x)`, `before(x, r)`, …) are functions, and give no fact:

| Expression | Type | Warnings |
| --- | --- | --- |
| `if includes(r, x) then x else null` | `number \| Null` | — |

## The functions of points and ranges

`before`, `after`, `coincides`, `during`, `finished by`, `finishes`, `includes`, `meets`, `met by`, `overlaps`, `overlaps after`, `overlaps before`, `started by` and `starts` give `true` or `false`, and `null` for an argument that is out of the domain (D-79). The type says which of the three a call is (`Feel.Analysis.Images.Range`, D-170):

- **Two points of one kind are compared by their sets.** `before(a, b)` is `a < b`, `after` is `a > b` and `coincides` is `a = b`: `before(n, 100)` is `true` for an `n` in `[0..10]`. Two points of kinds that cannot be compared (a number and a string, a date and a date and time) are `null` for sure, and two times, or two dates and times, can be `null`.
- **A range is not looked into.** Its type has the kinds of its endpoints and not the endpoints, and has the range with no endpoint, which is related to anything: the call is a `boolean`, and `null` where an endpoint of one can be of a kind that cannot be compared with one of the other (`before(s, r)` for a string and a `range<number>`).
- **`null`** is among the alternatives only for a `null` argument, a list that does not have exactly one item, a value that is neither a point nor a range, and a combination that is not a signature (`meets(1, 2)`).

| Expression | Type | Warnings |
| --- | --- | --- |
| `before(k, k)` | `boolean` | — |
| `before(x, k)` | `boolean \| Null` | — |
| `before(k, s)` | `Null` | — |
| `if n != null then before(n, 100) else null` | `boolean = true \| Null` | — |
| `if r != null then includes(r, k) else true` | `boolean` | — |
| `if r != null then before(s, r) else true` | `boolean \| Null` | — |
| `meets(k, k)` | `Null` | `argument_out_of_domain` |

## Limits

- No value set: a range's endpoints are not in its type.
- An endpoint that can be `null` is the comparison with `null` that the run makes (D-61), so it is read as the run does.

See also: [number](number.md), [list](list.md), [overloaded functions](overloaded-functions.md) (the point and range relations).
