This was my experience as well. Also, while it may theoretically be possible to compile native code with reason, the core focus of reasonml is javascript frontend development at the moment.
> On the native side, since Reason's just a syntax transform: yes, they work with Reason too. But the native workflow is currently work-in-progress and needs polish.
refmt formatting drives me a bit nuts, especially the.lines thing; it's steadily improving though.
One thing though - Belt is the WIP standard library (so OCaml), whereas JS is just bindings to JS, they're very different things. Belt produces much better JS when transpiled, and it seems a lot saner than the stdlib, but it isn't really anything to do with JS bindings.
And the pipe operator is |>, afaics |. is a typo on the Promises documentation page?
|> for reverse application, @@ for application, so
foo |> bar |> baz
and baz @@ bar @@ foo
are both the same as baz(bar(foo))
and they work excatly the same as in other ML languages someList
|. Belt.List.map(i => i + 1)
... because most Belt.List functions take the list as the first argument, and |> feeds its input as the last argument.Edit: apparently |. is BuckleScript, lots more discussion here: https://github.com/facebook/reason/issues/1452 ... just another instance of Reason still finding itself.
Give it two years though, and both will be amazing.
As in you can't override it? `shouldComponentUpdate` resolving to true in the absence of a custom method or PureComponent usage is standard React behavior: https://github.com/facebook/react/blob/7350358374036c0834ea6...
I should have been clearer: it'd be okay if `true` were simply the default, but the crux of the issue is that you can't even implement your own `shouldUpdate` as the function doesn't provide the previous props (like it does in React), so you have nothing to compare against – unless you laboriously store them yourself as state.
I was curious enough to glance at the React-Reason doc's and they say that `shouldUpdate` is passed a record called `oldAndNewSelf: {oldSelf: self, newSelf: self}`. Does that not have what is needed to implement the method without extra storage? For example, in standard React `shouldComponentUpdate` is passed `nextProps` & `nextState`, and since the method is in context of the previous render, we have everything we need to make the comparison without explicitly taking extra steps to store previous/next.
Maybe we are saying the same thing in different ways, I seem to be pretty good at that :).
The documentation is outdated, and the {oldSelf, newSelf} doesn't exist anymore. You had to use the `withRetainedProps` component for this to work, but that now results in an error message on compilation, telling you to use a reducerComponent instead.
I think it's something they intend to figure out a better solution for, but it's been put on the back-burner and meanwhile we're stuck with a non-solution. (Unless this is all wrong and I've been lied to and there's a better way, in which case, please enlighten me!)
Thanks for taking the time to clarify, and thanks for the original pros/cons post. I'm currently working on a mid-sized MVP project that is standard ES6 + Flow. I've recently been exploring our options for migrating to TypeScript or something like ReasonML. I've worked extensively with TypeScript, but am only starting to dip my toes into other options. You've been more helpful than just reading the documentation :)
https://medium.com/w3reality/working-with-option-using-maybe...
In the end, however, it's more bolted-on pieces that should be part of the language if you ask me.
Pros:
* Compile speed is mindblowing. As in, a big project compiles within a few seconds, and incremental compiles are instantaneous. The productivity gains of this cannot be overstated; you just don't get those moments anymore when you're waiting for webpack, your mind wanders off, lets just check HN real quick, ... no, you just stay in the flow. It's great. Elm, on the other hand, is sloooow.
* Type inference works really well. 9/10 times I don't even need to annotate anything and the compiler just knows. The only runtime errors I've ever run into were related to JS externals; the peace of mind knowing "if it compiles, it really works" is a game-changer even compared to TS.
* Error messages are (for the most part) fantastic and really helpful.
* Editor integration is solid, if a bit painful to set up at times.
* The ability to drop in the occasional chunk of dirty `[%bs.raw {...}]` is nice, and a clear advantage over Elm.
Cons:
* JSX support is a joke. You have to wrap every string in `(ReasonReact.String("bla"))`. You have to wrap arrays in `(ReasonReact.array(...))`. Passing children to components is supposed to be easy but will make you rip your hair out for sure. Etc., etc. But I'm sure it'll get there eventually.
* Refmt (the autoformatter) works pretty well but has lots of rough edges still. For instance, it removes all empty lines.
* State management isn't the greatest. Passing down props works alright but often it's just easier to keep things in a central Redux-ish store, especially because every. little. thing. needs to be passed down explicitly for the type checker to work.
* shouldComponentUpdate is hard-coded to `true` right now; there is no shallow comparison by default so everything always re-renders. Will be fixed medium- to long-term, I've been told. Workarounds exist but are pretty gnarly. Elm is much better at this.
* The standard library is a mess. ReasonML has its own, but forget about it; you'll fall back on Belt (the BuckleScript one), which 8/10 times has what you need but then is split into "Belt" parts and "Js" parts for unknown reasons and isn't always complete (e.g. I constantly need to convert from lists to arrays and back, because some utility functions only exist for one of the two, also for no real reason). There is piping syntax (|> and |.) but it's never clear which one to use; sometimes the data goes in first, sometimes it goes in last. You get used to it eventually, but Elm is a land of milk and honey in comparison.
* Lack of sugar: For instance, you'll end up making heavy use of option types, which are great obviously. Unfortunately there's no easy access syntax, so you end up with deeper and deeper levels of nested `Js.Option.getWithDefault()` and/or pattern matching.
* Documentation is meh overall. ReasonML is well documented, but it's only a very thin layer on top of BuckleScript. It took me hours of trial and error to figure out JS interop in practice, setting up "comparators" just to create a `set(int)` etc. You're effectively required to grok all of JS, Reason, Bucklescript, and OCaml at once, and draw from all of them to piece together your code. I think this will take another year or two to iron out.
Overall, I haven't found an option yet that truly works well. Elm is beautiful but slow and will drown you in boilerplate. ReasonML is fast and mighty but the UX isn't there yet. React+Redux+Typescript+Babel+Webpack have everything you need but it's a pain to set up and maintain, it's slow, and you can never trust it 100%.
(Edit: I should note that both Elm and ReasonML have amazing communities with very active, friendly and responsive dev teams that really and truly want the best for their languages. I have huge respect for both and I would encourage anyone to give them a try, just don't expect a perfectly polished experience yet.)