[BuckleScript 8.1 New Syntax]: Arrays and Lists


#1

I think we need dedicated threads for all the different syntax changes to discuss them separately (or grouped together where it makes sense, just not all in one thread). I start here with the new array and list syntaxes.

I, for one, like the default to [] instead of [||] because this confuses a lot of beginners coming from JS.

I just wondered if there would be a better alternative to list[] except of just swapping it with the [||] of arrays now, but I could not think of (at least it’s not just new List()).


BuckleScript 8.1: new syntax option
#2

What do you think of #[ 1,2 ]?


#3

At least that is even one char less than the old array.
But # is now also the prefix for polymorphic variants.

Not sure if that can be even more confusing for newcomers.


#4

dedicated threads sounds great. Even if link[1, 2, 3] is more to type I could remember it basically as soon as I saw it. The only thing that could be bad is that people would think it’s a typo and put a space in between the n and the [ however we could make that valid :man_shrugging:. You could maybe do something like %list[] like elixir does for their structs (%MyStruct{a: 2}) but then you’re adding syntax without function. However that’s not really different then #[] that @bobzhang mentioned.

The other question I have is, is “list” mean anything to most people? I think JS programmers don’t know the difference generally between arrays and singly linked lists. They are both “a list of things” in a human sense. Maybe, linked[] would be better? Although more characters… :sweat:


#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