Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create documentation for InclusiveRange #39

Merged
merged 4 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions versioned_docs/version-1.0/language/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,65 @@ dictionary.forEachKey(fun (key: String): Bool {
})
```

### Ranges in Loops

An `InclusiveRange` value can be used in a for-in statement in place of an array or dictionary. In this case,
the loop will iterate over all the values contained in the range, beginning with `range.start` and ending with `range.end`. E.g.

```cadence
let range: InclusiveRange<UInt> = InclusiveRange(1, 100, step: 2)
var elements : [UInt] = []
for element in range {
elements.append(element)
}
// after this loop, `elements` contains all the odd integers from 1 to 99
```

Note that in this example, even though `100` is the end of the `range`, it is not included in the loop because it cannot be reached with the given `start` and `step`.

The above loop is equivalent to:

```cadence
let range: InclusiveRange<UInt> = InclusiveRange(1, 100, step: 2)
var elements : [UInt] = []
var index = range.start
while index <= range.end {
elements.append(element)
index = index + range.step
}
// after this loop, `elements` contains all the odd integers from 1 to 99
```

In general, a for-in loop over an increasing range (a positive `step`) is equivalent to:

```cadence
var index = range.start
while index <= range.end {
// loop body
index = index + range.step
}
```

While a for-in loop over a decreasing range (a negative `step`) is equivalent to:

```cadence
var index = range.start
while index >= range.end {
// loop body
index = index + range.step // `range.step` here is negative, so this decreases `index`
}
```

Both can be equivalently rewritten to:

```cadence
var index = range.start
while range.contains(index) {
// loop body
index = index + range.step
}
```

### `continue` and `break`

In for-loops and while-loops, the `continue` statement can be used to stop
Expand Down
146 changes: 146 additions & 0 deletions versioned_docs/version-1.0/language/values-and-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1916,3 +1916,149 @@ Dictionary keys must be hashable and equatable.

Most of the built-in types, like booleans and integers,
are hashable and equatable, so can be used as keys in dictionaries.

## `InclusiveRange<T : Integer>`

An `InclusiveRange<T>` value represents a range of numerical values between two integers,
with the start and end numbers included in the range as suggested by the name.

A range value has a `start`, `end` and a `step`, which represents the interval at which the range's values are separated from `start` to `end`.

A range can be created using the `InclusiveRange` constructor, which can take two or three arguments.

In the case where the range is constructed with two arguments, the first argument is the `start` and the second is the `end`.
The `step` is inferred to be either `1` (when `end >= start`) or `-1` (when `end < start`). E.g.

```cadence
// start is 1, end is 100, step is 1
let range: InclusiveRange<UInt> = InclusiveRange(1, 100)
```

Optionally a third, labeled, non-zero `step` argument can be provided to specify a step other than `1`. E.g., the following range contains
all odd numbers from 1 to 100:

```cadence
// start is 1, end is 100, step is 2
let range: InclusiveRange<UInt> = InclusiveRange(1, 100, step: 2)
```

Note that in this example, even though the specified "end" of the range is 100, the last actual value the range can attain is 99.

If the specified `step` argument would progress the range away from the `end`, the creation will fail. E.g.

```cadence
// Throws an error because a step of -2 cannot progress from 1 to 100
let range: InclusiveRange<Int> = InclusiveRange(1, 100, step: -2)
```

A range requires a type annotation when created.

### `InclusiveRange<T>` fields and functions

A value of type `InclusiveRange<T>`, where `T` is a number type, has the following fields and functions:

-
```cadence
let start: T
```

The start of the range.

```cadence
// Declare a range of `Int`s
let range = let r: InclusiveRange<Int> = InclusiveRange(3, 9)

// Get the start of the range
let start = range.start

// `start` is `3`
```

-
```cadence
let end: T
```

The end of the range.

```cadence
// Declare a range of `Int`s
let range: InclusiveRange<Int> = InclusiveRange(3, 9)

// Get the end of the range
let end = range.end

// `end` is `9`
```

-
```cadence
let end: T
```

The end of the range.

```cadence
// Declare a range of `Int`s
let range: InclusiveRange<Int> = InclusiveRange(3, 9)

// Get the end of the range
let end = range.end

// `end` is `9`
```

-
```cadence
let step: T
```

The step of the range.

```cadence
// Declare a range of `Int`s with a `step` of 2
let rangeWithStep: InclusiveRange<Int> = InclusiveRange(3, 9, step: 2)

// Get the step of the range
var step = range.step

// `step` is `2`

// Declare a range of `Int`s without an explicit `step`
let rangeWithStep: InclusiveRange<Int> = InclusiveRange(3, 9)

/ Get the step of the range
step = rangeWithStep.step

// `step` is implicitly `1`
```

-
```cadence
access(all)
view fun contains(_ element: T): Bool
```

Returns `true` if the given integer is in the `InclusiveRange` sequence, and `false` otherwise.

Specifically, for some `InclusiveRange` `r` defined with `start`, `step` and `end`, `r.contains(x)` returns true if either:
* `start <= end` and there exists some integer `i >= 0` such that `start + i * step = x` and `x <= end`
* `start > end` and there exists some integer `i >= 0` such that `start - i * step = x` and `x >= end`

```cadence
// Declare a range of `Int`s with a `step` of 2
let rangeWithStep: InclusiveRange<Int> = InclusiveRange(3, 9, step: 2)

// `contains` is `true`
var contains = range.contains(5)

// `contains` is `true`
var contains = range.contains(9)

// `contains` is `false`
contains = range.contains(6)

// `contains` is `false`
contains = range.contains(11)
```