microsoft / qsharp-language

Official repository for design of the quantum programming language Q# and its core libraries
MIT License
235 stars 56 forks source link

QEP 3: multidimensional array proposal #49

Closed cgranade closed 3 years ago

cgranade commented 3 years ago

This PR represents an initial version of a proposal for #39.

bettinaheim commented 3 years ago

@cgranade One question: How can the dimensions of a multidimensional array be accessed?

cgranade commented 3 years ago

@cgranade One question: How can the dimensions of a multidimensional array be accessed?

My thought was that this is the role of Shape2<'T> : 'T[,] -> (Int, Int), Shape3<'T> : 'T[,,] -> (Int, Int, Int), and so forth functions.

cgranade commented 3 years ago

As per discussions offline, I'll go on and take the action items to:

bettinaheim commented 3 years ago

Copy-pasting some notes from exploring a syntax alternative for literals:

What should opening and closing delimiters be for inner levels of nesting?

Are spaces allowed between [ and |?

Do we use [|| for higher than 2D or nested [|?

What should be checked at compile time?

bettinaheim commented 3 years ago

Further discussions on [| and |] vs simply | for inner items:

vxfield commented 3 years ago

I'm not following this closely, so I'll just drop a raw idea here that you may have already considered (based on many other languages implementations). 1) Allow arrays of arrays as usual, by nesting [ .. , .. ] constructs. Example: [ [1, 2, 3], [3, 4, 5] ] 2) Have a Matrix<T> type that takes, in its constructor, the dimensions of the matrix. Example: let myMatrix = new Matrix<int>(2,3); // creates a 2x3 integer matrix 3) The constructor of this Matrix type requires at least the size of the first dimension, but allows the user to pass an extra arbitrary number of dimensions. Example: public Matrix(int dim1size, int[] extraDimSizes = null) 4) This Matrix type implements an interface to load data. This method is responsible to check that the input parameter dimensions matches the matrix's dimension. Example: myMatrix.Load([ [1, 2, 3], [3, 4, 5] ]); // succeeds myMatrix.Load([ [1, 2, 3], [3, 4] ]); // throws exception 5) Add a syntactic sugar in the compiler to call the Load method together with the constructor: let myMatrix = new Matrix<int>(2,3)[ [1,2,3], [4,5,6] ]; does the same as let myMatrix = new Matrix<int>(2,3); myMatrix.Load([ [1, 2, 3], [3, 4, 5] ]); 6) If the compiler can resolve all the symbols at compilation time as constants, the compiler calls the Load method at compile-time, potentially letting the user know that they are trying to do something invalid. Otherwise leave it become a runtime error.

bamarsha commented 3 years ago

Can't reuse [| and |], but that's ok since we don't need another basic sequence type. [Edit BH: I wouldn't be so sure about that.]

I think [| |] is probably not practical as a separate sequence delimiter even if we use | | for multidimensional arrays, because of confusion like this:

// 2D array
[ |1, 2, 3| ]

// 2D array or new sequence literal?
[|1, 2, 3|]

So if we expect another type of sequence literal, I think we should plan for that to use delimiters other than [| |], or use neither [| |] nor | | for multidimensional arrays.

bettinaheim commented 3 years ago

Copy-pasting the conclusions from our discussions today here:

Very brief recap of the reasoning: Having a type Int[,] gets pretty messy in how the type looks compared to how the item access behaves. The consistent notation would be to have Int[,][] in be an array of 2D arrays. Accessing an item in it then requires an indexing first into the outer and then the inner array: arr[0][0,1], switching the order according to the shoes-and-socks principle. E.g. C# deviates from that to align the two such that the type of an array of 2D arrays would be int[][,]. Going with [|Int|] by comparison like e.g. Rust is cleaner and matches the literal syntax. The literal syntax correspondingly should be [|1,2|, |3,4|] to match the [| |] of the type while keeping the type syntax clean (no additional [] as suggested previously for [ [|1,2|], [|3,4|] ]).