From 2bb279608f6d6444ff378044fd2604066a50f2ad Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Fri, 5 Aug 2022 23:32:47 +0900 Subject: [PATCH 1/2] Slice generator --- proposals/p1927.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 proposals/p1927.md diff --git a/proposals/p1927.md b/proposals/p1927.md new file mode 100644 index 0000000000000..70705d9e5d9fb --- /dev/null +++ b/proposals/p1927.md @@ -0,0 +1,96 @@ +# Slice generator + + + +[Pull request](https://github.com/carbon-language/carbon-lang/pull/1927) + + + +## Table of contents + +- [Problem](#problem) +- [Background](#background) +- [Proposal](#proposal) +- [Details](#details) +- [Rationale](#rationale) +- [Alternatives considered](#alternatives-considered) + + + +## Problem + +Slices of arrays is a popular way to extract subarray of array. They also may +be used for generating arrays. + +## Background + +There is no requirements for background. + +## Proposal + +Introduce slice generators. + +## Details + +Slice syntax is `a:b:s`. Here, `a` is the beginning of slice, `b` is the end of +slice and `s` is the step in slice. In array indexing, `:s` can be omitted, then +it means that step is 1. If `a` is omitted, slice starts from the beginning of +array. The same situation is for `b`, but slice ends at the end of arrays. `:` +is the same as `::`. If `s` is negative, lower and upper bounds are replaces +each other. + +Slice generator may return `i32`, `i64`, `i128` and unsigned versions of them. + +Slice as generator of array: +```carbon + var array: auto = (1:5:2); // array = (1,3,5) + var arrav: auto = 1:5:2; // arrav = (1,3,5) +``` +Round brackets may be omitted. + +In operator `[]` of array, slices can be used in the following ways: +``` + var array: auto = (1:5:2); // array = (1,3,5) + var a1: auto = array[:]; // a1 = (1,3,5) + var a2: auto = array[::]; // a2 = (1,3,5) + var a3: auto = array[:1]; // a3 = (1,3) + var a4: auto = array[::-1]; // a4 = (5,3,1) + var a5: auto = array[:2:-1]; // a5 = (5) +``` + +Note, `auto` for slice of one element gives an array containing one element. + +## Rationale + +It has an effect to [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write). + +## Alternatives considered + +Most of programming languages have syntax the same or close to proposed. + +In Pascal, [subrange](https://wiki.freepascal.org/subrange_types) is available. +Using similar syntax, slice may produce arrays: +```carbon + var arr: auto = 1 .. 4; +``` +will generate `[1, 2, 3, 4]` (round brackets may be omitted). Unfortunately, +such syntax does not allow generate array with specific step between elements. + +Another way is function call. The most simple and can be implemented via +standard library. +```carbon + var arr: auto = slice(/*low=*/ 1, /*high=*/ 4, /*step=*/ 1); +``` +Here, `step` is optional argument. This way lacks possibility to specify only +low or high bounds or even skip both of them. +It will lead to the following code for slicing of whole array that is not simple +to read, understand, and write: +```carbon + var arr: auto = (1, 2, 3); + var arr_copy: auto = arr[slice(lbound(arr), ubound(arr))]; +``` +`lbound` and `ubound` returns lower and upper bounds of `arr`, respectively. From 4af3c6221ed1b3eee1dbc5da7ece14c48d04cce9 Mon Sep 17 00:00:00 2001 From: "Igor S. Gerasimov" Date: Sun, 14 Aug 2022 02:45:51 +0900 Subject: [PATCH 2/2] Update proposal --- proposals/p1927.md | 92 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/proposals/p1927.md b/proposals/p1927.md index 70705d9e5d9fb..186483590cf5c 100644 --- a/proposals/p1927.md +++ b/proposals/p1927.md @@ -16,6 +16,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - [Background](#background) - [Proposal](#proposal) - [Details](#details) + - [Library API](#library-api) - [Rationale](#rationale) - [Alternatives considered](#alternatives-considered) @@ -23,8 +24,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ## Problem -Slices of arrays is a popular way to extract subarray of array. They also may -be used for generating arrays. +Slices of arrays is a popular way to extract subarray of array. They also may be +used for generating arrays. ## Background @@ -40,19 +41,31 @@ Slice syntax is `a:b:s`. Here, `a` is the beginning of slice, `b` is the end of slice and `s` is the step in slice. In array indexing, `:s` can be omitted, then it means that step is 1. If `a` is omitted, slice starts from the beginning of array. The same situation is for `b`, but slice ends at the end of arrays. `:` -is the same as `::`. If `s` is negative, lower and upper bounds are replaces -each other. +is the same as `::`. If `s` is negative and `a` or `b` or both are skipped, +instead of `a`, upper bound is and, instead of `b`, lower bound is. Slice has +closed range. + +Compilation or runtime errors are: + +- if `s` is zero; +- if `a` is greater than `b` when `s` is positive; +- if `a` is less than `b` when `s` is negative. + +`:` has the lowest priority for making possible `a[1:N-1]` without any brackets. Slice generator may return `i32`, `i64`, `i128` and unsigned versions of them. -Slice as generator of array: +Slice as generator of arrays: + ```carbon - var array: auto = (1:5:2); // array = (1,3,5) - var arrav: auto = 1:5:2; // arrav = (1,3,5) + var array1: auto = (1:5:2); // array1 = (1,3,5) + var array2: auto = (1:5); // array1 = (1,2,3,4,5) ``` -Round brackets may be omitted. + +Round brackets, `a`, and `b` must be presented, `s` may be omitted, In operator `[]` of array, slices can be used in the following ways: + ``` var array: auto = (1:5:2); // array = (1,3,5) var a1: auto = array[:]; // a1 = (1,3,5) @@ -64,9 +77,25 @@ In operator `[]` of array, slices can be used in the following ways: Note, `auto` for slice of one element gives an array containing one element. +### Library API + +Internally, slice is presented as `Slice(low, high, step)` that may return +arrays or `Slice`. While constructing, `low`, `high` are calculated by way of +calling arrays properties. + ## Rationale -It has an effect to [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write). +- [Performance-critical software](/docs/project/goals.md#performance-critical-software) + - In performance-critical sofrware, like modelling, sometimes slices of + arrays may be used. For example, for updating sub-arrays. There is no + necessary to go to low-level for choosing several elements. +- [Software and language evolution](/docs/project/goals.md#software-and-language-evolution) + - Simplifying to access to sub-ranges of arrays. +- [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write) + - Less code will be written for working with ranges. +- [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code) + - Here, there is a problem with interacting with std::span/std::mdspan + comes from C++. ## Alternatives considered @@ -74,23 +103,46 @@ Most of programming languages have syntax the same or close to proposed. In Pascal, [subrange](https://wiki.freepascal.org/subrange_types) is available. Using similar syntax, slice may produce arrays: + ```carbon var arr: auto = 1 .. 4; ``` -will generate `[1, 2, 3, 4]` (round brackets may be omitted). Unfortunately, -such syntax does not allow generate array with specific step between elements. -Another way is function call. The most simple and can be implemented via +will generate `[1, 2, 3, 4]` (round brackets may be omitted). + +Advantages: + +- Clear and popular for ranges in mathematic's notation +- Close to Rust and Pascal + +Disadvantage: + +- Unfortunately, such syntax does not allow generate array with specific step + between elements. + +Another way is function call. The most simple and can be implemented by way of standard library. + ```carbon var arr: auto = slice(/*low=*/ 1, /*high=*/ 4, /*step=*/ 1); ``` -Here, `step` is optional argument. This way lacks possibility to specify only -low or high bounds or even skip both of them. -It will lead to the following code for slicing of whole array that is not simple -to read, understand, and write: -```carbon - var arr: auto = (1, 2, 3); - var arr_copy: auto = arr[slice(lbound(arr), ubound(arr))]; -``` + +Here, `step` is optional argument. + +Advantage: + +- Close to internal representation; +- May work similarly to `std::span` + +Disadvantage: + +- This way lacks possibility to specify only low or high bound or even skip + both of them. It will lead to the following code for slicing of whole array + that is not simple to read, understand, and write: + + ```carbon + var arr: auto = (1, 2, 3); + var arr_copy: auto = arr[slice(lbound(arr), ubound(arr))]; + ``` + `lbound` and `ubound` returns lower and upper bounds of `arr`, respectively.