# `Feel.Value.Range`
[🔗](https://github.com/FeeJai/BDM/blob/feel-v0.1.0/apps/feel/lib/feel/value/range.ex#L1)

The FEEL type `range` (DMN 1.6, section 10.3.2.7): an interval between two
endpoints.

Ranges come from interval syntax such as `[1..10)`, from prefix tests such as
`< 5` and `>= x`, and from the `range` built-in. A prefix test leaves one side
undefined: `< 5` has no start, and `>= 5` has no end. An undefined endpoint is
`nil` and its side is never included.

The type of a range is `range<T>`, where `T` is the type of its endpoints.

## Fields

  * `:start` and `:end` - the endpoints, or `nil` when undefined.
  * `:start_included` and `:end_included` - whether each endpoint belongs to
    the range. These are the `start included` and `end included` properties.
  * `:operator` - how the range was written: `nil` for an interval, `[1..10)`, or
    the comparison of a prefix test, `:lt`, `:lte`, `:gt`, `:gte`, `:eq` or `:neq`, for
    `(< 10)` and the others (D-61). The properties are those of Table 42 either way, but the
    two are not equal: `(< 10) = (null..10)` is `false`, and so is `(= 10) = [10..10]` (TCK
    `0068#range_006`, `#range_010`), as the specification has it, "the same endpoints and the
    same comparison operator or inclusivity flag" (notes 02, A-07). `(!= 10)` has the
    endpoint on both sides, left out of the range, and a value is in it when it is not equal to the endpoint:
    that is a decision (D-61). The TCK had the properties of `(!=10)` in `0074#range_012` and has commented the case
    out (dmn-tck/tck PR 671), so nothing asserts them; only `(!=10) = (!=10)` is (`0068#range_012`).

The struct does not check that the endpoints are of one kind or in order;
building a range from arbitrary values is the evaluator's job, and it decides
when that yields `null`.

# `endpoint`

```elixir
@type endpoint() :: Feel.Value.t()
```

# `operator`

```elixir
@type operator() :: nil | :lt | :lte | :gt | :gte | :eq | :neq
```

How a range was written: an interval (`nil`), or the comparison of a prefix test.

# `t`

```elixir
@type t() :: %Feel.Value.Range{
  end: endpoint(),
  end_included: boolean(),
  operator: operator(),
  start: endpoint(),
  start_included: boolean()
}
```

# `new`

```elixir
@spec new(endpoint(), endpoint(), keyword(boolean())) :: t()
```

Builds a range.

## Options

  * `:start_included` - defaults to `false`.
  * `:end_included` - defaults to `false`.

Raises `ArgumentError` for any other option or a non-boolean flag.

    iex> Feel.Value.Range.new(1, 10, start_included: true)
    %Feel.Value.Range{start: 1, end: 10, start_included: true, end_included: false}

# `type`

```elixir
@spec type(Feel.Type.t()) :: Feel.Type.t()
```

Returns the descriptor of `range<T>` for endpoints of type `endpoint`.

# `value?`

```elixir
@spec value?(term()) :: boolean()
```

Returns `true` for a `t:t/0` with boolean inclusion flags.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
