-
Notifications
You must be signed in to change notification settings - Fork 54
Proposal for removing default-initialized new array expressions #48
Conversation
anpaz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference would be:
- Remove
new - Provide the methods proposed by Sarah:
EmptyArray<T>()ConstantArray(n, value)
- Provide sugar for:
T[]==>EmptyArray<T>()T[n]==>ConstantArray(n, Default); and have the compiler fail for anyTthat has no default (likeQubitandString).
|
I agree with @anpaz's suggestion |
Currently, both of these functions already exist in Microsoft.Quantum.Arrays:
I think following the above suggestion from @SamarSha, if we want to annotate types of expressions, we should likely do so as a general feature and not as a one-off for empty arrays. Since types in Q# always follow values in declarations (e.g.: |
This means that users will need to memorize not only what the default values are for each type, but which types have default values. It saves a few characters when writing, but IMO it's harder to read than explicitly writing out the value you want to use. I think we should optimize for readability and consistency here. By contrast, if you require array initializers to include the value explicitly, users only need to memorize the initialization syntax. Always including the value also more intuitively generalizes to initializing arrays of non-default values: instead of needing to switch from |
|
@cgranade @SamarSha I agree that Regarding using Ideally I would suggest
I would be fine coming up with a new operator for this; would something like this work for example? let myArray = [0] : len(4) # same as [0, 0, 0, 0] |
I don't think this works either. In Q#, it's only type names that come after a I'm not sure why this has problems with type classes. Why can't there be a type class "Multipliable" that contains arrays and numbers, and |
|
Thanks, @alan-geller , that makes sense. For completeness, @SamarSha also mentioned the issue of overloading with
Aside from whether this would lead to a huge amount of work or not, I'm curious if this would make sense: let myArray = [0 for i in 0..3] # same as [0, 0, 0, 0] |
To me, that makes perfect sense. It's just like |
If I understood right, it was that @SamarSha's proposal for a typeclass / concept representing types supporting (On a side note, I say magma and not semigroup since there's no way at the type system level to enforce associativity; strictly speaking, |
Sorry for the Haskell, but is this what you mean? class Multipliable a where
(*) :: Num b => a -> b -> a
-- or
(*) :: Num b => b -> a -> aThis type class seems to have unfortunate implications. For example, if
I don't think |
|
@guenp @alan-geller Since the resolution to the syntax question is a bit buried in the rather long thread above, let me recap here:
The reason for the choice of syntax is the following:
With this interpretation, we can build on it in the future and potentially fully support partial application also for such built-in syntax constructs (to be worked out in a separate proposal), meaning things like these: // In all cases, the exact type of the callable will be inferred based on the first usage.
let buildTuple = (1,2,_); // callable to construct a tuple
let populateArray = [_, size=10]; // callable to construct an array
let createArray = [Zero, size=_]; // callable to construct an array
let multiply = _ * _; In combination with array comprehension (to be worked out and confirmed in a separate proposal) and multidimensional arrays (a proposal is in progress), we get the following: // all of these create an array of arrays of length 3
[0, size=(3,2)]
[[x*x for x in 1..2], size=3]
[[0 size=2], [0 size=3], [0 size=4]]
[[1,2], [3,4,5], [6,7,8,9]]
// all of these create a 2D array of shape (3,2)
#[0, size=(3,2)]
#[[x*x for x in 1..2], size=3]
#[[0 size=2], [1 size=2], [2 size=2]]
#[[1,2], [3,4], [5,6]]
// all of these create a 3D array of shape (4,3,2)
#[0, size=(4,3,2)]
#[#[[x*y for x in 1..2] for y in 1..3], size=4]
#[#[[1,2], [3,4], [5,6]], #[[1,2], [3,4], [5,6]], #[[1,2], [3,4], [5,6]], #[[1,2], [3,4], [5,6]]] |
I think we can have both behaviors "just work" if we separate the |
|
Yes, if the operator names are different, then I don't think there's any issue. My concern was only with re-using |
Co-authored-by: bettinaheim <34236215+bettinaheim@users.noreply.github.com>
Co-authored-by: bettinaheim <34236215+bettinaheim@users.noreply.github.com>
bettinaheim
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working through this! This has turned into a great proposal and has spawned many useful conversations!
This is the proposal for issue microsoft/qsharp-compiler#46.