Open dsyme opened 6 years ago
Another comment:
ImmutableArray<'T>
type, not provide our own.Just to emphasise; getting this done and available soon is way more important than whatever syntax we end up with or whatever we decide to call it.
Using mutable arrays sucks, but gets done anyway because for some tasks everything else is just too hopelessly slow.
Just to emphasise; getting this done and available soon is way more important than whatever syntax we end up with or whatever we decide to call it.
Which is exactly the pain point of C++ - feature bloat and lack of cohesiveness.
@Happypig375 - and yet right now we're forced to use incorrect code or even MORE incoherent and ugly syntax via third party libraries.
Get something on the table - if we weren't so terrified of breaking changes we can always take steps to improve/alter it later.
and yet right now we're forced to use incorrect code or even MORE incoherent and ugly syntax via third party libraries.
That can be said so for almost all of the suggestions in this repository.
Get something on the table - if we weren't so terrified of breaking changes we can always take steps to improve/alter it later.
Python 2/3, VB6/VB.NET, Perl5/Perl6, ...
if we weren't so terrified of breaking changes we can always take steps to improve/alter it later.
@varon Nobody is terrified it's just a terrible idea. Breaking things stops adoption, loses customers and creates distrust in the future of a product. It's the cornerstone of good design to keep things compatible. Personally, I'm very happy with the design of F#. It's clean and concise, and for the majority of tasks, stopping yourself from writing foo.[3] <- x
goes a long way.
I agree that using immutable libraries is a pain, but it's not hard and doesn't introduce real problems. Dedicated syntax would be nice-to-have, but if you've followed the discussion you know it's not that simple. Luckily, we have a feature switch that we can use to test-drive new implementations, while a feature isn't completed yet.
But before anything, we'll need concensus. Nobody likes to do the work, only to find out months later that there isn't concensus. But considering the discussion is active, I've good hopes we'll get agreement soon. Then we'll need a volunteer to do the heavy lifting, as my guess is this may be a rather tough task (depending on what features is decided upon).
Or maybe someone already has a PR or a fork ready so we could play around with this feature, that would be nice too. After all, it's open source ;).
Late to the party, but is the syntax [::]
available, e.g. [: 1; 2; 3 :]
, or does that collide or cause ambiguities with something else? I'm also partial to adopting int immarray
as a shortcut for ImmutableArray<int>
.
@TIHan
We should definitely use the framework's
ImmutableArray<'T>
type, not provide our own.
Really? System.Collections.Immutable is not part of the default reference set for .NET Library (.NET Standard 2.0 or 2.1). This means every single F# project would need a reference to this assembly. Even in 2020 I'm somehow not happy with that.
Could you explain more on what you think the tradeoffs are here? Is S.C.Immutable now "part of the framework" enough that a 100% mandatory FSharp.COre dependency is desirable??
Rules of discussion for this thread going forward
assume that there are no breaking changes allowed
assume we're talking about a type that is semantically equivalent to System.Collections.Immitable.ImmutableArray
"ReadOnly" is indeed out as a name for reasons @TIHan mentions
S.C.I. is the de facto package in .NET for this sort of stuff and has undergone tremendous hardening and stability as a result of being use ubiquitously throughout the Roslyn and other massive codebases at Microsoft. I think we should very strongly consider incorporating it, or at least an F# implementation of a subset of it, into FSharp.Core for the purposes of having a standard immutable array type. I wouldn't really be supportive of a bespoke implementation.
What's the issue with adding the package dependency? The main issue I see isn't about including another dependency (it's 2020 - people have dependencies in their apps), but some potential confusion with things like F# lists vs. ImmutableList<'T>, which would be available to them via transitive references.
No breaking change for language version 5?
S.C.I. is in netcore3.1. So it will be in dotnet5. Presumably you won't see an extra dependency when using dotnet5. In any case the extra package will be a small and short-lived problem.
I would also be strongly in favor of using S.C.I. We use these collections very frequently in our codebase (with some aliases in F# for brevity, which I would propose to include). Adding new collections just so they can be shipped in F# Core will hinder interop and only increases the already fair amount of concrete collection types commonly seen in .NET and F#.
Also F# already does something like that by using its own List
type and aliasing the S.C.G. List
as ResizeArray
, instead of providing its own dynamic array implementation.
Of course, S.C.G. List
is in the standard framework unlike S.C.I., so the infrastructural concern of an external dependency doesn't apply. But the UX is similar.
Are there any perfomance reasons for F# to have a new immutable array type? Like, can compiler do some optimizations on it when on ImmutableArray
it couldn't?
Like, can compiler do some optimizations on it when on ImmutableArray it couldn't?
The first thing that comes to mind is that it can eliminate null checks, something I believe is already done now for lists and arrays (the null check is in Core, but gets eliminated when used with F# code).
Other things currently not done in ImmutableArray is optimizations when target size is known (i.e. for things like map
). I can envision something like, but not the same as Array.zeroCreate
for arrays (which, btw, is not really optimized currently, but that's another discussion), and then use mutability internally. (the current ImmutableArray uses a Builder, we should measure if there's enough performance gain over that that warrants a self build implementation).
Then it will have to point to a ReadOnlyMemory
or confusion will occur.
Arr
comes to my mind.
let x = arr [1; 2] // looks similar to seq {1; 2;} let y = x |> Arr.map string // type inference for collection literals // e.g. in Feliz Html type: static member button (children: ReactElement arr) = ... Html.button [ prop.text "Increment" prop.onClick (fun _ -> dispatch Increment) ]
I am also coming from C# and I wouldn't be confused at all to have array
being immutable and introduce MutableArray
similarly to list
and ResizeArray
. It actually makes sense to me.
I also like the suggestion to have all types being alias around the immutable collections IF it does bring too much performance penalty. I am converting an application I started in C# and most of my types are ImmutableXXX
types and so far I am doing the change because the syntax is too cumbersome for F#.
Regarding the fact that it will force a dependency upon immutable collections library. I do see a lot more projects starting to have a dependency upon this. I would say that it would be worth asking if SCImmutable should not be part of the default fwk moving forward.
I don't know if this was implied by @SamuelBerger on his last comment but I think it would be nice if there was only the []
syntax with the array
or list
prefix to define the type. We could still fallback to the old-way by having []
being implicitly understood as list
but I would still recommend a warning/message to encourage people to move to the new syntax. Also maybe the prefix could be optional if the type is known:
let x = array [ 1; 2 ] // prefix is mandatory as we don't know
Html.button [ ... ] // prefix is optional as we know a list is expected
I don't know if this was implied by @SamuelBerger on his last comment but I think it would be nice if there was only the
[]
syntax with thearray
orlist
prefix to define the type. We could still fallback to the old-way by having[]
being implicitly understood aslist
but I would still recommend a warning/message to encourage people to move to the new syntax. Also maybe the prefix could be optional if the type is known:
I meant 2 different things, naming and type inference for collection literals.
For the naming part:
Probably the hardest thing is to decide its name.
ImmutableArray is too long, especially for a module IArray looks like an interface FlatList breaks with industry naming, it looks too odd. XArray, ZArray are possible if we are desperate – e.g. just make a new F# convention that ZThing is an immutable version of Thing
My day to day F# progamming is mostly around List.xxx, Seq.xxx, Array.xxx and ResizeArray.xxx (custom module) and unfortunately the conversion between them. List because of its immutability and beauty. Seq mostly when types come from the BCL or C#. Array for its performance (when I know a list may contain thousands of elements I just have a bad conscious using List and lean towards Array or Seq 😬). If ImmutableArray was built in, all my collection usage would essentially collapse to this single type. I can imagine, that would be the case for a lot of people. That's why I think the name should be very short and easy to type. I think Arr would be the perfect name.
This part would have a huge impact by its own.
For the second part I was just quoting the suggestion from above 'type inference for collection literals' by @piaste and @dsyme.
Are there any approaches to literal syntaxes would be acceptable? e.g.
- Add a range of new syntaxes [! a; b !] ?
- 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"))? While plausible it is a significant addition which may give worse error messages, and increase reliance on typing context and type annotations.
[ ... ] would be a 'significant addition' but I'm afraid the only good solution for front-end programming to replace List with the native JS Array. It would be intersting to hear the opinons of @alfonsogarciacaro and @Zaid-Ajaj what a difference it would make in e.g. Feliz.
I support @brettfo 's [: :]
over arr [ ]
.
[ ]
and [| |]
for list and array. ImmutableArray construction is more like list and array construction than a seq { }
expression so the syntax should follow that.arr [ ]
gives the inaccurate feeling of creating a list and then applying the function arr
to it.[: :]
is easier to format across multiple lines without feeling guilty about undentation.There are other ideas in this thread about using a flexible [ ]
for construction and/or matching and having the compiler understand that this syntax can apply to ImmutableArrays. This is a great idea and might presage some exciting changes in the language, where [ ]
and Option
and ( )
get interpreted as ImmutableArray
and ValueOption
and ValueTuple
respectively based on a project setting, resolving the confict between the most often useful type vs. easiest type to read and write. But it's a large change and long-term discussion that shouldn't prevent putting in ImmutableArrays now using the conventions we currently have.
Flexible [ ]
is also orthogonal to a [: :]
syntax:
[ ]
would need to apply to arrays too for symmetry, and we'd still need a [: :]
syntax for ImmutableArray for symmetry.[: :]
does not prevent creating and matching varous types with [ ]
in future.Perhaps [: :]
is ok although it really screams type annotation
to me in F#. But I do get the point that something is needed for symmetry for such a critical addition to the F# armoury.
@charlesroddie Do you have opinions on the name of a standard F# abbreviation for ImmutableArray<T>
?
@cartermp do you really think we could take the S.C.I dependency for FSharp.Core? If so then we should go ahead and do this once a name is chosen. People are promoting "Arr" but no choices are great.
Vote:
Arr.map
and int arr
and [: 1;2;3 :]
👍 KArray.map
and int karray
and [: 1;2;3 :]
❤️ CArray.map
and int carray
and [: 1;2;3 :]
😄 IArray.map
and int iarray
and [: 1;2;3 :]
🚀 ImmArray.map
and int immarray
and [: 1;2;3 :]
👀 CList.map
and int clist
and [: 1;2;3 :]
🎉 ImArray.map
and int imarray
and [: 1;2;3 :]
😕 @dsyme I'd prefer a little shorter imarray
.
@dsyme I'd prefer a little shorter
imarray
.
Me too. It's a little more fluid to type quickly. imarray
would be my first choice, followed by the double-m immarray
.
@dsyme I'd prefer a little shorter imarray.
I've added that an an option (but are you proposing ImmArray
, ImArray
or Imarray
for the module name??`
@dsyme ImArray
is consistent.
Anyone know the name for this emojii?
It's :confused:
!
Trying to figure out how to respond with 😏but GitHub isn't letting me. I prefer the ImArray
@matthewcrews use the :confused: one
Have you considered using double brackets? [[ 1;2;3 ]] I think it looks extra strong, immutable.
Could it be thought of in a different way?
Rather than an ImmutableArray could it be something like an indexable list? The F# list is already immutable so it would be a case of indicating that it can be randomly accessed, something like IndexedList
or RandomAccessList
?
That might yield some alternative ideas?
@aaronpalmer that would make jagged lists (i.e. int list list
) ambiguous, unfortunately
One thing I like about F# is that it makes you do a little extra work every time you want something mutable. I like "Arr" for that reason, because it is less friction than any of the others. It is the easiest to type, the first one in a sorted documentation index, etc.
I agree with @jschiefer, there's a tradition in F# to encourage good practice (such as immutability) through simpler code such that a dev often finds they're doing the right thing without even thinking about it. Only "Arr" seems to respect this tradition. Also IArray and similar suggestions seem to overstep the boundaries of interop where IStuff comes with a lot of baggage.
@lfr It would be against F# tradition to have two names, Array and Arr, one an abbreviation of the other, where the beginner has nothing to help understand the difference
Note there's also a suggestion of "Irray".
@lfr It would be against F# tradition to have two names, Array and Arr, one an abbreviation of the other, where the beginner has nothing to help understand the difference
I agree, I forgot to add to my comment that I'm not particularly fond of Arr 🙁
Note there's also a suggestion of "Irray".
I like the idea but the word makes me angry, not sure why, perhaps it makes me think of Ire... What about Krray?
Will you add matrix or it is a part of ImmutableArray(ImmutableArray2D)?
What about Imray.map
and int imray
and [: 1;2;3 :]
It's not a prefix or abbreviation of an existing name. It's pronounceable, it's not based on prefixing the word "array", and doesn't risk the confusion of irray
and array
sounding similar.
Just a thought...
If the literals used < >, would that make a DSL that looked just like XML/HTML possible? Perhaps generics using <> and attributes using [<>] makes this impossible?
I can't help myself but I read imarray as "I'm array". And I agree with @jschiefer so I voted for arr.
I know it's a little wordy but I still kept my vote for "ImmArray" and would probably prefer "ImmutableArray" if it weren't for System.Collections.Immutable.ImmutableArray
already being a thing.
Maybe too late for suggestions but I'd consider "arrayi" . Treat the immutable property as a qualifier rather than being integral to the name. I did scan the thread for this suggestion but might have missed it, on mobile.
What about
Imray.map
andint imray
and[: 1;2;3 :]
This one just jumps out at me as 'right' The same length to type as array
, looks sufficiently different to spot it when reading, even easy to say. Could you add this one to the list @dsyme ?
@realparadyne I agree, I also like that it's pronounceable
What about
Imray.map
andint imray
and[: 1;2;3 :]
This one just jumps out at me as 'right' The same length to type as array, looks sufficiently different to spot it when reading, even easy to say. Could you add this one to the list @dsyme ?
I'll run another poll with a smaller set of suggestions including this one
Here's a new suggestion:
Block.map
and int block
and [: 1;2;3 :]
When I think of "block" it conveys both the shape (array-like) and the properties (can't be changed, it's a block, which sort of sounds like something immutable)
Also, I can see F# education material "chapter 2" laying out the differences between
Somehow the fact they each have different names appeals to me.
Second round of voting with top three suggestions plus "Imray" and "Block". You can vote for more than one suggestion.
You can work on the assumption that the type name is an alias for System.Collections.Immutable.ImmutableArray
.
Also please work on the assumption that this type occurs very, very often in F# coding and education material and APIs going forward, often used as a replacement for both lists and arrays.
Arr.map
and int arr
and [: 1;2;3 :]
👍Block.map
and int block
and [: 1;2;3 :]
😄 ImmArray.map
and int immarray
and [: 1;2;3 :]
❤️Imray.map
and int imray
and [: 1;2;3 :]
🎉ImArray.map
and int imarray
and [: 1;2;3 :]
🚀
For people coming to this thread afresh, the RFC is here: https://github.com/fsharp/fslang-design/blob/main/RFCs/FS-1094-immarray.md
I propose we work out how to make one particular immutable array type normative in F# programming "in the box", including in Fable programming.
The existing way of approaching this problem in F# is to use a user-supplied package of collections such
System.Collections.Immutable
Description
One particular thing that is a hole in our library is the lack of an immutable array data structure in regular F# coding. There are lots of use cases for this and it is easy enough to implement efficiently, e.g. here (originally from the compiler codebase) though there are other approaches.
I’m particularly aware that Fable and the Elmish design pattern is popularizing the use of immutable data for important model descriptions more and more and we should be helping improve the situation for that kind of programming
The main question is to how to make on immutable array type normative in F# coding
Add a bespoke immutable array to FSharp.Core.
Encourage people to take a dependency on System.Collections.Immutable and add a reference to it to our standard templates. However we would still presumably want an FSharp.Core module making it look and feel like a normal F# collection, but we wouldn't want FSharp.Core to have a dependency on System.Collections.Immutable.
Probably the hardest thing is to decide its name.
ImmutableArray
is too long, especially for a moduleIArray
looks like an interfaceFlatList
breaks with industry naming, it looks too odd.XArray
,ZArray
are possible if we are desperate – e.g. just make a new F# convention thatZThing
is an immutable version ofThing
Block
wins the dayRelated questions are
Extra information
Estimated cost (XS, S, M, L, XL, XXL): M
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply: