From 54ff22e528b1ac3518136e9de22aa557569dbe15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 2 Apr 2019 16:57:01 +0200 Subject: [PATCH 1/3] Improve description of range literal Also includes documentation of begin-less and end-less ranges introduced by https://github.com/crystal-lang/crystal/pull/7179 --- syntax_and_semantics/literals/range.md | 28 +++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/syntax_and_semantics/literals/range.md b/syntax_and_semantics/literals/range.md index 368e3d80f..d9946f59e 100644 --- a/syntax_and_semantics/literals/range.md +++ b/syntax_and_semantics/literals/range.md @@ -1,14 +1,32 @@ # Range -A [Range](http://crystal-lang.org/api/Range.html) is typically constructed with a range literal: +A [Range](http://crystal-lang.org/api/Range.html) represents an interval between two values. It is typically constructed with a range literal, consisting of two `..` or three dots: -```crystal -x..y # an inclusive range, in mathematics: [x, y] -x...y # an exclusive range, in mathematics: [x, y) +* `x..y`: Two dots denote an inclusive range, including `x` and `y` and all values in between (in mathematics: `[x, y]`) . +* `x...y`: Three dots denote an exclusive range, including `x` and all values up to but not including `y` (in mathematics: `[x, y)`). -# Example: +```cr (0..5).to_a # => [0, 1, 2, 3, 4, 5] (0...5).to_a # => [0, 1, 2, 3, 4] ``` +NOTE: Range literals are often wrapped in parenthesis, for example if it is meant to be used as the receiver of a call. `0..5.to_a` without parenthesis would be semantically equivalent to `0..(5.to_a)` because method calls and other operators have higher precedence than the range literal. + An easy way to remember which one is inclusive and which one is exclusive it to think of the extra dot as if it pushes *y* further away, thus leaving it outside of the range. + +The literal `x..y` is semantically equivalent to the explicit constructor `Range.new(x, y)` and `x...y` to `Range.new(x, y, true)`. + +The begin and end values do not necessarily need to be of the same type: `true..1` is a valid range, although pretty useless `Enumerable` methods won't work with incompatible types. They need at least to be comparable. + +Ranges with `nil` as begin are called begin-less and `nil` as end are called end-less ranges. In the literal notation, `nil` can be omitted: `x..` is an end-less range starting from `x`, and `..x` is an begin-less range ending at `x`. + +```cr +numbers = [1, 10, 3, 4, 5, 8] +numbers.select(6..) # => [10, 8] +numbers.select(..6) # => [1, 3, 4, 5] + +numbers[2..] = [3, 4, 5, 8] +numbers[..2] = [1, 10, 3] +``` + +A range that is both begin-less and end-less is valid and can be expressed as `..` or `...` but it's typically not very useful. From c3c74821fa7e0fe0af34f4d54d76cedc2ceca9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Tue, 2 Apr 2019 18:28:31 +0200 Subject: [PATCH 2/3] fixup! Improve description of range literal --- syntax_and_semantics/literals/range.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/syntax_and_semantics/literals/range.md b/syntax_and_semantics/literals/range.md index d9946f59e..0680003d8 100644 --- a/syntax_and_semantics/literals/range.md +++ b/syntax_and_semantics/literals/range.md @@ -1,6 +1,6 @@ # Range -A [Range](http://crystal-lang.org/api/Range.html) represents an interval between two values. It is typically constructed with a range literal, consisting of two `..` or three dots: +A [Range](http://crystal-lang.org/api/Range.html) represents an interval between two values. It is typically constructed with a range literal, consisting of two or three dots: * `x..y`: Two dots denote an inclusive range, including `x` and `y` and all values in between (in mathematics: `[x, y]`) . * `x...y`: Three dots denote an exclusive range, including `x` and all values up to but not including `y` (in mathematics: `[x, y)`). @@ -10,7 +10,7 @@ A [Range](http://crystal-lang.org/api/Range.html) represents an interval between (0...5).to_a # => [0, 1, 2, 3, 4] ``` -NOTE: Range literals are often wrapped in parenthesis, for example if it is meant to be used as the receiver of a call. `0..5.to_a` without parenthesis would be semantically equivalent to `0..(5.to_a)` because method calls and other operators have higher precedence than the range literal. +NOTE: Range literals are often wrapped in parentheses, for example if it is meant to be used as the receiver of a call. `0..5.to_a` without parentheses would be semantically equivalent to `0..(5.to_a)` because method calls and other operators have higher precedence than the range literal. An easy way to remember which one is inclusive and which one is exclusive it to think of the extra dot as if it pushes *y* further away, thus leaving it outside of the range. From 911dafcef799ecb2c228188651d68bc1b75df9fe Mon Sep 17 00:00:00 2001 From: r00ster Date: Tue, 2 Apr 2019 19:07:10 +0200 Subject: [PATCH 3/3] Update syntax_and_semantics/literals/range.md Co-Authored-By: straight-shoota --- syntax_and_semantics/literals/range.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syntax_and_semantics/literals/range.md b/syntax_and_semantics/literals/range.md index 0680003d8..41149391f 100644 --- a/syntax_and_semantics/literals/range.md +++ b/syntax_and_semantics/literals/range.md @@ -10,7 +10,7 @@ A [Range](http://crystal-lang.org/api/Range.html) represents an interval between (0...5).to_a # => [0, 1, 2, 3, 4] ``` -NOTE: Range literals are often wrapped in parentheses, for example if it is meant to be used as the receiver of a call. `0..5.to_a` without parentheses would be semantically equivalent to `0..(5.to_a)` because method calls and other operators have higher precedence than the range literal. +**NOTE:** Range literals are often wrapped in parentheses, for example if it is meant to be used as the receiver of a call. `0..5.to_a` without parentheses would be semantically equivalent to `0..(5.to_a)` because method calls and other operators have higher precedence than the range literal. An easy way to remember which one is inclusive and which one is exclusive it to think of the extra dot as if it pushes *y* further away, thus leaving it outside of the range.