[BuckleScript 8.1 New Syntax]: Arrays and Lists


#5

This is not described in the blogpost so maybe I don’t know where to look but what is going to happen to [x, ...xs] both in terms of adding an element to the head of the list and pattern matching?
I assume (based on the comparison to js) that we’ll be able to pattern match on arrays now but based on the footnote in that section the compiler will always give a warning that array might not be of the length we’re trying to ‘destructure’. How does it work with pattern matching?
How will pattern matching look for lists (wether using list[...] or any other “prefix”) and when potentially unified with the likes of map[...] how will the “pattern-match”-ability be communicated (as you should be able to pattern match on lists but not on maps)?

NB: Rust has vec![...] which looks very similar so the syntax doesn’t really scare me. However in rust this is a macro and it’s not baked into the language.


#6

ReasonML / Buckelscript gives data types that do not exists in JS.
Hiding this will probably just late the learning experience.
I dislike this point for 2 reasons :slight_smile:

  • using [ ] for arrays move the gap from JS/BS to BS/ReasonML. I really think BS could extends ReasonML for JS devs inclusivity (like it did for ->) but should not have a syntax that exists in BS and ReasonML with a different meaning
  • ~Since both compile to Arrays in JS, why is it a problem that BS devs use List first ?~ (made a mistake, my bad) I think it’s better to use List because using Array will promote mutability in newcomers code.

If [||] is problematic, it may be changed for something smaler like < > or | | but [ ] for arrays don’t seems a good idea


#7

Lists don’t compile to arrays so it’s understandable why arrays are being made the “star” collection data type.


#8

This should work:

let ls = list[0, ...tail]

switch ls {
| list[] => 0
| list[1] => 1
| list[x, ..._] => x
}

Still, there’s no way to use spreads in PMs agains arrays. So nothing has changed in this regard except the syntax.


#9

I thought about:

// Array
let x = [1, 2, 3]
// List
let y = [1; 2; 3]

But there’s no distinction for empty/one element lists :frowning: unless we do list[] and list[a] but then it might be confusing after all.


#10

I prefer keeping the current list syntax and change array syntax to something like what @bobzhang mentioned #[1, 2].

Personally I like list to be first class container due its recursive nature (pattern matching, fp), and Immutablity. Lists are more natural for me.

Having alternative syntax for arrays (better than [||]) and keeping current list syntax is more likely to be applied for both refmt 4 and bs reason parser because list is first class container on ocaml platform.


BuckleScript 8.1: new syntax option
#11

I agree with you completely. We only actually use arrays for React as most of the times you actually need to work with your collections (add elements, filter, reduce) and it’s much easier to do with lists than it is with arrays.

Our team has JS background and not prior OCaml experience. Yet we found working with lists much more comfortable and only use arrays for interop and React. I don’t think that “js devs prefer arrays” is a 100% true.

I would also like to bring up one issue mentioned in Discord and not mentioned here. If we move forward with list[...] then what will list[0] mean? Will it mean accessing an element with 0 index or will it mean a list with one element 0


#12

Always the latter AFAICT. Apparently, it’s not possible to use [] to access elements in lists, only in arrays:

let list = list[0] // => list<int> 
let xs = list[0] // => list<int>
let head = list->Belt.List.get(0) // => option<int>
let head = xs->Belt.List.get(0) // => option<int>
let head = xs[0] // error

#13

So … this means we can’t create an array called list and access it with array indexing op…

EDIT: actually, \"list"[0] works.


#14

This will definitely be more confusing and I daresay worse for DX than having [||] for arrays. And looking at object["key"] syntax that we will have for js objects I think list[..] might not be a good idea. If bs team has a gut feeling that making the array data type so important will help with adoption and potentially bring more people into our community I personally could live with [| 1, 2, 3 |] being used for lists. It’s reversing the meaning from OCaml perspective but it’s not that bad:)


#15

Over the years, I found myself mostly using arrays rather than lists in UI related code b/c majority of them end up in the rendering cycle anyway hence List.toArray cost on the hot path is something I wouldn’t willing to pay. As well as an external JSON contains arrays most of the time so converting arrays to lists and then back to arrays during rendering/api calls doesn’t make a lot of sense in my opinion.


#16

I think the main downside of this approach is that as a begginer you’re often having to write bindings between JS and ReasonML as you transition your codebase over. This means that the “default” thing is often a pit of failure in the past (if I use lists I have to constantly convert them to arrays). Whereas this new syntax makes it so that new people do the JS friendly thing and can kind of ignore linked lists till they figure out what makes them awesome. Generally (but not always) arrays are small enough in the browser that the performance implications of them don’t really matter. Also I think JS runtimes store arrays as more of a hash-map rather than an actual C++ array which means there’s less copying when you have to resize and add elements to it. Don’t quote me on that :man_shrugging:

I think one of the places you see this the most is when you’re using React. You start by making a list data structure, then want to display it on the screen and a beginner is all of a sudden faced with this decision of linked lists VS arrays that never was a problem when they just programmed JS. Making arrays the default delays this learning till a time it’s more meaningful.

However I do :heart: linked lists!


#17

The more I think about it I actually really like this suggestion. I don’t think list[] is all that meaningful (JS programmers see lists and arrays as the same thing) AND it makes linked lists feel like part of the language… just not the default. In elixir we have a similar concept where {:ok, "asdf"} is a tuple and %{a: 2} are maps. Also having the character that diffs them in the front allows it to be very specific rather than the typical OCaml convention of [a; 2, 3] being a list with a tuple in it :fearful:.


#18

Oh that’s a really good suggestion. Could something like [;] work for an empty array?


#19

Won’t list be a protected keyword so you can’t bind a list to the name list, ie you can do let a = list[0] and access the index with a[0] but you can’t do let list = list[0] so there can’t be a list[0] for access.

Was wondering if you could do access but just read alex’s comment above so this may be mute anyway.


#20

I think it creates all these edge cases that aren’t too explicit


#21

Such is the nature of language design I suppose. The [1;2;3] is a good suggestion as it bridges js with [1,2,3] for arrays and ocaml for lists [1;2;3]. (not sure if it’s distinct enough from each other though). Also single element lists to consider.
Bob’s #[1,2,3] is not bad either but I always found # symbol extremely noisy. I’m not sure what possible options are with the parser but a less noisy prefix would be good. Something short would be a benefit as list[....] is fairly verbose.

borrowing from above:

let ls = #[0, ...tail]

switch ls {
| #[] => 0
| #[1] => 1
| #[x, ..._] => x
}

#22

I’m mostly ok with this. I do prefer lists, but I’ve been working on performance-sensitive code for the last few months and the more we switch to arrays the better it performs. For functional recursion lists are essential, and we still do that where performance doesn’t matter, but I’ve found that for most list-based algorithms an equivalent (but less pure) array-based algorithm is usually much faster in JS. What I lose in write speed I more than make back in read speed (likely due to memory locality and CPU caches).

Pattern matching works on [||] arrays today, with the same caveats and warnings. It’s an underlying OCaml feature. Array patterns are fixed length so it’s not widely useful, but I have found it to be handy at times.


#23

I understand that Reason Native and Buckleson are diverging and keeping them inline is a non-goal but maybe we can have our cake and eat it too? Based on this it’s within OCaml’s “powers” to redefine the [] so we can have array in “pervasives” and use List.[] when we need to. Can this be an option? This way there is a “sensible default” and no additional syntax required. But then again I might be not seeing the bigger picture.

NB. Purescript that has been brought up in a conversation about “reason forgetting its functional roots” has [] for arrays and not lists ironically


#24

this means we can’t create an array called list

Don’t call an array list =)
Right now you can see that there’s nothing preventing you from doing let list = .... But after this solidifies we’ll properly remove that possibility. So you won’t be able to use list as an identifier, which removes this naming possibility but avoids the mistake of trying to do what you said.