I propose we consider doing type-directed resolution of the [...] syntax if used with a non-list known type.
type SomeApi() =
static member SomeEntryPoint(xs: ImmutableArray<_>) = ...
SomeApi.SomeEntryPoint([1; 2; 3])
The main thing here is that whenever a method needs a collection (of more or less any kind), as input, you can always use, for example, [1;2;3] and not think about it.
This means F# APIs can reasonable choose to adopt ImmutableArray or other such collection types for inputs without particularly changing user code.
If this is considered reasonable, the question arises about when this is allowed. For example, it's possible that it should just be at method argument position - F# has a tradition of only applying such "magic" (e.g. lambda --> delegate, ParamArray and more recently op_Implicit) only at method applications. However in theory it could also be at any position by type-directed resolution, e.g.
let x: ImmutableArray<_> = [1;2;3]
For some reason people don't seem to mind these transformations at method calls.
From a previous suggestion:
Have the [ ... ] syntax resolved in a type-directed way (e.g. "if the target type is known to be a collection C with a builder pattern or IEnumerable constructor, then treat the syntax as if it is constructing a C, otherwise treat it as a regular F# list"))?
The syntax would work with
- list types
- array types by obvious translation
- Set/Map types (we would add a builder for these)
- ReadOnlySpan or Span, using stackalloc.
- Mutable collection types that have a constructor (optionally with a capacity arg), and an 'Add' method to add the elements.
- System.Collections.Immutable through a builder pattern definable via extensions or naming
This is somewhat related to the ListCollector type in F# 6 which is use as our builder for F# immutable lists and which gave the performance results described here. The only subtlety there is the presence of AddManyAndClose that allows lists to be collected in tail position without copying the list.
The underlying problem here is that we over-emphasise the "list" type in F# - that is, in an API designer wants to get nice, minimal callside syntax, they have no choice but to accept F# lists. However this has problems
- It can be relatively highly allocating
- It's not pleasant from C#
- It's probably not the data representation used inside the API. For example the F# quotations API uses
list throughout. but internally converts to arrays.
Pros and Cons
The advantages of making this adjustment to F# are:
- nice syntax for many more collection types.
The disadvantages of making this adjustment to F# are:
- performance can vary significantly based on type annotation
- harder to work out what actual objects are being allocated
- you need a type annotation or strongly known type
- there are two ways to do arrays, i.e.
[| 1;2 |] and via known type ([ 1; 2 ]: int array)
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Related suggestions: (put links to related suggestions here)
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.
I propose we consider doing type-directed resolution of the
[...]syntax if used with a non-list known type.The main thing here is that whenever a method needs a collection (of more or less any kind), as input, you can always use, for example,
[1;2;3]and not think about it.This means F# APIs can reasonable choose to adopt ImmutableArray or other such collection types for inputs without particularly changing user code.
If this is considered reasonable, the question arises about when this is allowed. For example, it's possible that it should just be at method argument position - F# has a tradition of only applying such "magic" (e.g. lambda --> delegate,
ParamArrayand more recentlyop_Implicit) only at method applications. However in theory it could also be at any position by type-directed resolution, e.g.For some reason people don't seem to mind these transformations at method calls.
From a previous suggestion:
The syntax would work with
This is somewhat related to the ListCollector type in F# 6 which is use as our builder for F# immutable lists and which gave the performance results described here. The only subtlety there is the presence of AddManyAndClose that allows lists to be collected in tail position without copying the list.
The underlying problem here is that we over-emphasise the "list" type in F# - that is, in an API designer wants to get nice, minimal callside syntax, they have no choice but to accept F# lists. However this has problems
listthroughout. but internally converts to arrays.Pros and Cons
The advantages of making this adjustment to F# are:
The disadvantages of making this adjustment to F# are:
[| 1;2 |]and via known type([ 1; 2 ]: int array)Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Related suggestions: (put links to related suggestions here)
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.