Range expressions are formed with {{rangeTo}} functions that have the [operator form of {{..}}|Operator overloading#Binary operations] which are complemented by [*in* and *!in*|Operator overloading#in]:
{jet}
// Check range membership, i.e. contains
// (optimized for Ints)
if (a in 1..100) {
  print("in range")
}

// Iterate through a range, i.e. iterator()
// (optimized for Ints)
for (x in 1..100) {
  print(x)
}
{jet}

A {{rangeTo()}} function may return whatever type one likes, but there's a common convention:
* For enumerable types like {{Int}}, {{rangeTo()}} returns an {{IterableRange}} object that supports both checking membership with {{contains()}} (*in*) and iterating with {{iterator()}}.
* For other ordered types (like {{String}} or {{Double}}), it returns a {{Range}} that only supports checking membership with {{contains()}}.

h3. What's next

* [This expressions]
* [Tuples]
* [Type casts]
