fsharp / fslang-suggestions

The place to make suggestions, discuss and vote on F# language and core library features
345 stars 21 forks source link

A normative immutable array type #619

Open dsyme opened 6 years ago

dsyme commented 6 years ago

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

  1. Add a bespoke immutable array to FSharp.Core.

  2. 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.

Related questions are

  1. Would want a bespoke functional update syntax “{ arr with 3 = expr }” or “{ arr with n = expr } or “arr.[n=expr]”.
  2. Would the type feel right from F# code – good ergonomics etc
  3. What library dependencies would the type induce
  4. How do other collections from System.Collections.Immutable feel to use from F#?

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:

realvictorprm commented 3 years ago

Now in all seriousness. Imray is the best, writes well, is short and sounds fancy :3

Victor P. R. Müller mueller.vpr@gmail.com schrieb am So., 17. Jan. 2021, 22:50:

Brick

Charles Roddie notifications@github.com schrieb am Sa., 16. Jan. 2021, 18:57:

@dsyme https://github.com/dsyme How many more rounds? :) Can we have top 3 from last round (Block, ImArray, Arr), and three new ones (row, irray, imray)? With voting for any number of options (since three of these are similar)?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/fsharp/fslang-suggestions/issues/619#issuecomment-761606264, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGB4Z4CX5J6POBCGOIKQBQLS2HHRPANCNFSM4EDWZKWQ .

woojamon commented 3 years ago

Block in French is "bloc" and in Dutch "blok". One character less and no clashing! "Diversity in tech" also for non English words in programming languages so to speak :)

Blok looks too much like the Australian "Bloke" to me, but I like bloc. But if we want to prioritize brevity and diversity, then I hereby propose (liè) or (dān)!It would certainly endear F# to the vast Chinese software community. (Imagine the weight F# could throw around in Microsoft with a user base that large!)

lfr commented 3 years ago

Bloc is good too, it kind of has all the advantages of block because that's how most people will read it, yet somehow there's no confusing it with code block, no hijacking a term that could be used for things that you can actually create with F#, no confusing it with blocking, and it's even shorter than block. I think Beam still wins on its linear/one-dimensional connotation, but not by much.

laenas commented 3 years ago

Block in French is "bloc" and in Dutch "blok". One character less and no clashing! "Diversity in tech" also for non English words in programming languages so to speak :)

Playing the translation game, Row up north is Rad and I mean, that'd be more fun to write, yeah?

dsyme commented 3 years ago

Given the voting and discussion so far, I imagine we'll go for block.

I did a small draft trial PR of using block inside the F# compiler here: https://github.com/dotnet/fsharp/pull/10895/files. Two substantial issues noted so far

Other comments:

  1. It's intrinsically messy to adapt to a new linear collection type in an existing codebase, e.g. to decide the boundaries of where to use block, array, list, seq, avoid copying etc.

  2. There just aren't many upsides to adding a subtle abbreviation like arr or imarray to the very core of F# - It's hard enough to adapt to a new linear collection type (e.g. to decide the boundaries of where to use block, array, list, seq), let alone making your code cryptic as well.

  3. Although the name is not used by other functional languages we're doing ourselves a favour by settling on it here. "seq" was also not in common use, for example, but it's a fine name for IEnumerable. If OCaml had used block in 2003 we would have used it in F# too. Other ML-class languages had things like "vec" but those just aren't what we want.

  4. Of all the suggested whole-word names "block" wins for me. bloc isn't too bad, I've a penchant for French in codebases ever since working with a guy who liberally sprinkled French comments throught.

If other people could trial "block" in their codebase and send feedback I'd be grateful.

dsyme commented 3 years ago

Also, in that trial I needed to write a utility to compare an array and a block, e.g.

let arrayPathEq (y1: string[]) (y2: string[]) = ..

became

let arrayPathEq (y1: string[]) (y2: string[]) = ..

let blockPathEq (y1: string block) (y2: string block) = ..

let arrayBlockPathEq (y1: string[]) (y2: string block) = ...

This is the kind of place where it becomes really really helpful to be using a distinct name, c.f. the more cryptic

let arrayPathEq (y1: string[]) (y2: string[]) = ..

let arrPathEq (y1: string arr) (y2: string arr) = ..

let arrayArrPathEq (y1: string[]) (y2: string arr) = ...
Happypig375 commented 3 years ago

Let's have a final round of voting... (Part 1/3)

Block is the currently proposed name as seen in @dsyme's comments above.

The syntax [: 1; 2; 3 :] is set in stone.

Reaction Module Suffix
👍 Block block
👎 Bloc bloc
😄 Bar bar
🎉 Beam beam
❤️ Brick brick
🚀 Ray ray
👀 Row row
😕 (Another name)

Next part of names: https://github.com/fsharp/fslang-suggestions/issues/619#issuecomment-762880757

davedawkins commented 3 years ago

If other people could trial "block" in their codebase and send feedback I'd be grateful.

Do you mean by using a type alias like "type block = ", etc?

woojamon commented 3 years ago

Was Series considered?

JaggerJo commented 3 years ago

Was Series considered?

Still my favourite.

Happypig375 commented 3 years ago

Final round voting part 2/3:

Reaction Module Suffix  
👍 Series series
👎 Arr arr (Rejected by @dsyme)
😄 Irray irray (Rejected by @dsyme?)
🎉 ImArray imarray (Rejected by @dsyme)
❤️ ImmArray immarray (Rejected by @dsyme)
🚀 Vec vec (Rejected by @dsyme)
👀 Vector vec / vector (Rejected by @dsyme?)
😕 (Another name)

Previous part of names: https://github.com/fsharp/fslang-suggestions/issues/619#issuecomment-762859284 Next part of names: https://github.com/fsharp/fslang-suggestions/issues/619#issuecomment-762888957

IltaySaeedi commented 3 years ago

Let's have a final round of voting...

In this poll there is no "ImArray". I like "Beam" and "Row" .

I like "Sprig" too. It is peacful, you cannot replace a leaf with another one so it's immutable. You can pick a leaf (.Item(index) or .[index]) or cut it and pick a slice of it. Removing some leaves(filter)... . However it is hard to pronounce and it is not as hard as "Beam".

lfr commented 3 years ago

Also missing: strut

Happypig375 commented 3 years ago

Final round voting part 3/3:

Reaction Module Suffix  
👍 Strut strut  
👎 Pad pad
😄 Slab slab (Rejected by @dsyme)
🎉 Chunk chunk (Rejected by @dsyme)
❤️ Pile pile
🚀 Rar rar
👀 ImmerArray immerarray (Rejected by @dsyme?)
😕     (Another name)

Previous part of names: https://github.com/fsharp/fslang-suggestions/issues/619#issuecomment-762880757

woojamon commented 3 years ago

Also, in that trial I needed to write a utility to compare an array and a block, e.g.


let arrayPathEq (y1: string[]) (y2: string[]) = ..

became


let arrayPathEq (y1: string[]) (y2: string[]) = ..

let blockPathEq (y1: string block) (y2: string block) = ..

let arrayBlockPathEq (y1: string[]) (y2: string block) = ...

This is the kind of place where it becomes really really helpful to be using a distinct name, c.f. the more cryptic


let arrayPathEq (y1: string[]) (y2: string[]) = ..

let arrPathEq (y1: string arr) (y2: string arr) = ..

let arrayArrPathEq (y1: string[]) (y2: string arr) = ...

I just want to re-emphasize this point. As much I like the symmetry of Irray to Array, something like arrayIrray would take more brain cycles to distinguish in spoken conversation from arrayArray, irrayArray and irrayIrray, and would likely need clarification most times.

wekempf commented 3 years ago

Of the current suggestions I'd vote Arr. I'd suggest something a bit unusual, though. Linear. It's unusual because the word linear is an adjective, not a noun, but it sure does express the idea better than Block does, at least to my mind, and it certainly won't have conflicts with any existing usages.

reinux commented 3 years ago

This is slightly out of left-field, but since there are 6 votes for "Another name" and we're otherwise divided as of now, how about "Index"?

1: a list (as of bibliographical information or citations to a body of literature) arranged usually in alphabetical order of some specified datum (such as author, subject, or keyword)

Pros:

Obvious problems:

lfr commented 3 years ago

My problem with index is the same as block, we're hijacking a word useful to describe things in your code for something for which it's hardly a perfect description by all accounts

kspeakman commented 3 years ago

Oh I love imray (said with same cadence as array). Feels like it could catch on as a name in other communities. Pretty easy to recall when you need an immutable array... bookends the concept. The rest don't feel quite right to me because of prior art in programming/math (block, series, row, index) or too loose of an association (construction stuff, strut, ray, etc).

reinux commented 3 years ago

Having let some time pass, I'm beginning to agree that the drawbacks of Index might be pretty significant.

I'm surprised imray hasn't been mentioned more. Seems like a good candidate. In the same vein, irray seems all right too.

woojamon commented 3 years ago

imray was mentioned a week ago here: https://github.com/fsharp/fslang-suggestions/issues/619#issuecomment-759102597

kspeakman commented 3 years ago

A challenge with irray is the difference with array when spoken is subtle. So in pairing scenarios it could be confusing, especially if different accents come into play.

Happypig375 commented 3 years ago

@kspeakman @reinux Imray has the least votes in the previous round of voting: https://github.com/fsharp/fslang-suggestions/issues/619#issuecomment-759428584

kspeakman commented 3 years ago

Yes, I just saw the thread linked from Slack. I didn't see where it was voted on initially (hundreds of hidden comments). I guess that means it is a dead suggestion? My apologies then. 🙃

realvictorprm commented 3 years ago

just here to promote Imray another round too 😉

lfr commented 3 years ago

Is there a reason range was never voted on?

Karamell commented 3 years ago

I'd vote for rib

travis-leith commented 3 years ago

How about a Wall. Walls are made of bricks and can be iterated. Both walls and their bricks are immutable.

Also, I think we can get Mexico to pay for it.

travis-leith commented 3 years ago

Or maybe Pillar?

lfr commented 3 years ago

How about a Wall. Walls are made of bricks and can be iterated. Both walls and their bricks are immutable.

Also, I think we can get Mexico to pay for it.

I think a Fence looks more like an array, especially this type:

image

It's also cheaper than a wall, which is important in case Mexico decides not to pay for our silliness for some reason.

IltaySaeedi commented 3 years ago

Merlon: A merlon is the solid upright section of a battlement (a crenellated parapet) in medieval architecture or fortifications.

source: https://en.m.wikipedia.org/wiki/Merlon

lfr commented 3 years ago

Merlon is the name of the one thing, unless you're suggesting "Merlons".

laenas commented 3 years ago

I highly suspect all the thesaurus archeology being done is more distracting than functionally helpful towards resolution. Especially with so much subjectivity in pronunciation, reading, comprehension, association, and experience involved in such a decision. block has the votes, BDFL support, and POC behind it, so lets roll with it and in a year's time forget this was ever such a tooth-grinding decision :)

lfr commented 3 years ago

in a year's time forget this was ever such a tooth-grinding decision

Says he who won't have to deprecate an entire project.

travis-leith commented 3 years ago

I think perhaps the best option is to go with the F# specific type that resembles Array, called Farray. No name clashes with any existing projects, none of the linguistic confusion mentioned by @laenas , does what it says on the tin. Why complicate matters further?

lfr commented 3 years ago

I think perhaps the best option is to go with the F# specific type that resembles Array, called Farray. No name clashes with any existing projects, none of the linguistic confusion mentioned by @laenas , does what it says on the tin. Why complicate matters further?

Yep, that's the same idea as bloc for those who really love the word block, it's a made up word that's still 100% recognizable by everyone.

matthewcrews commented 3 years ago

I like bloc for the fact that it is short and does not appear to be commonly used to describe other programming constructs. bloc isn't made up though. It's a real word to describe a set of countries or political parties that are aligned. Still seems like a possibly good option though.

wekempf commented 3 years ago

Range, like Block has lots of existing meanings, none of which are as a collection type. Unlike Block, though, Range is a concept often applied in the collection space (the value passed to "slice" methods that get a "sub-collection"). I'd vote for Block before Range.

travis-leith commented 3 years ago

Range, like Block has lots of existing meanings, none of which are as a collection type. Unlike Block, though, Range is a concept often applied in the collection space (the value passed to "slice" methods that get a "sub-collection"). I'd vote for Block before Range.

How would you feel about Bloc instead of Block?

wekempf commented 3 years ago

Bloc is just an abbreviation. Normally I dislike abbreviating, but in this case it at least addresses concerns about name clashes such as those that lead @lfr to claim he'll have to deprecate a repo. However, that's all it does. It doesn't help with the communication problems with overloading a name. That's why I prefer Arr. While that's also an abbreviation meant to avoid a name clash, at least both usages are talking about roughly the same concept.

matthewcrews commented 3 years ago

I would like to point out that bloc is not an abbreviation. The definition is a group of aligned political parties or countries which kind of makes sense (https://www.dictionary.com/browse/bloc). An immutable array is a set of aligned data underneath. Makes sense to me 🤷‍♂️.

realparadyne commented 3 years ago

Is there a reason range was never voted on?

Range is already a .net type. https://docs.microsoft.com/en-us/dotnet/api/system.range?view=net-5.0

roboz0r commented 3 years ago

I'd be quite happy with block as the new term. I dislike imray and variants as contractions and compound words are much worse to say and also difficult to distinguish from array at a glance in code. My only other suggestion would be column. It's short and has the right connotations. The use of a column in a database refers to elements of a single type which is consistent here and a column in a building refers to a core element that holds up the rest of the building and shouldn't be modified. I dislike row as a database row contains multiple types and an immutable array does not.

lfr commented 3 years ago

I also like that just by having one less letter, bloc makes signatures less clunky, here's the block's version of Array.append's tooltip:

// block1:'T block -> block2:'T block -> 'T block 😵
Block.append

And the version with bloc:

// bloc1:'T bloc -> bloc2:'T bloc -> 'T bloc
Bloc.append

Signature characters are prime real estate 🏛

dsyme commented 3 years ago

Hi all,

It's time to close out this long discussion. We will proceed to the RFC using block and Block.

Thanks Don

dsyme commented 3 years ago

The RFC is here: https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1094-block.md

dsyme commented 3 years ago

Discussion can continue here: https://github.com/fsharp/fslang-design/discussions/528

dsyme commented 2 years ago

Just to say we started using the block naming in the F# compiler codebase and eventually backed it out in favour of explicit ImmutableArray. It was my choice to do this after experiencing it in practice. So my intuition that this naming was good enough was incorrect.

SamuelBerger commented 2 years ago

Just to say we started using the block naming in the F# compiler codebase and eventually backed it out in favour of explicit ImmutableArray. It was my choice to do this after experiencing it in practice. So my intuition that this naming was good enough was incorrect.

😭😭😭 (my code is full of blocks and I like it... a pity it does not become standard F#)

matthewcrews commented 2 years ago

@dsyme would it be possible to get some info on why block was not a good solution? I'm asking purely for my own understanding. I'm curious what the pain point is that precludes this addition to F#.