News for hackers. Stuff that matters.
Re:ReasonML – React as first intended by skosch on Thursday May 24, 2018 @11:40AM (#17145074)
Currently using Reason. Here's what they don't tell you:

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

Re:ReasonML – React as first intended by joobus on Thursday May 24, 2018 @01:44PM (#17146416)
> 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.

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.

https://reasonml.github.io/docs/en/faq.html

Re:ReasonML – React as first intended by justincormack on Thursday May 24, 2018 @02:53PM (#17147100)
Yeah the native code story has been deferred and using OCaml directly is currently far easier. This will change.
Re:ReasonML – React as first intended by RobertKerans on Thursday May 24, 2018 @07:07PM (#17149304)
Yea, thays been very much my experience as well. Still a little bit off usable imo, docs are still very iffy, and there's only really Real World OCaml as a great learning resource for the actual language.

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
Re:ReasonML – React as first intended by skosch on Friday May 25, 2018 @09:57AM (#17153726)
I don't know where (or if) |. is documented, I think I saw someone use it in a Github thread somewhere. I use it all the time – for instance

    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.

Re:ReasonML – React as first intended by RobertKerans on Saturday May 26, 2018 @08:30PM (#17164890)
Ah, that makes sense. But that's, afaics, a completely undocumented operator which breaks standard (subject last) ML convention - I get why it's very useful for interoperability with JS but jeez that isn't great work on the documentation front; I've been using Reason for small personal projects and libraries for the last six months and didn't even know that was a thing that had been defined
Re:ReasonML – React as first intended by rdrey on Thursday May 24, 2018 @12:29PM (#17145624)
Thanks for this. I was looking for a thorough comparison with Elm. If you had to start a brand new project, which would you choose? Do you believe that struggling through the <JS, Reason, Bucklescript, and OCaml> learning curve is worth it?
Re:ReasonML – React as first intended by skosch on Thursday May 24, 2018 @12:53PM (#17145909)
I don't know. Take a weekend and try out both, you'll learn what you like best. Both are great and frustrating at the same time, it depends on what you consider the bigger pain point. If you don't mind slow compile times, difficult JS interop, no JSX at all, lots of boilerplate, you can have code that is pure shining beauty and elegance (Elm) ... or you can have an absolute beast of an engine (Ocaml) covered in nasty duct tape with sticky residue and silver spraypaint on top (BS/ReasonML).

Give it two years though, and both will be amazing.

Re:ReasonML – React as first intended by lsadam0 on Thursday May 24, 2018 @12:26PM (#17145600)
> shouldComponentUpdate is hard-coded to `true`

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

Re:ReasonML – React as first intended by skosch on Thursday May 24, 2018 @12:45PM (#17145816)
Well, you can (it's called `shouldUpdate` in ReasonML) but it doesn't work. You have to make it a reducerComponent, manually keep track of the previous props as if they were mutable state, and then do the comparison explicitly. This is from a conversation I had just a few days ago on the offical Discord chat.
Re:ReasonML – React as first intended by lsadam0 on Thursday May 24, 2018 @12:54PM (#17145923)
There very well could be something I'm not understanding. What you are describing still sounds like standard React.JS behavior. Unless you use a PureComponent, or explicitly implement your own `shouldComponentUpdate` method, then `shouldComponentUpdate` will always resolve `true`.
Re:ReasonML – React as first intended by skosch on Thursday May 24, 2018 @01:02PM (#17146020)
You're not wrong; it's stateless components I'm talking about.

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.

Re:ReasonML – React as first intended by lsadam0 on Thursday May 24, 2018 @01:16PM (#17146158)
I'm going to blame any communication breakdown on the fact that I know nothing about ReasonML or React-Reason. However, the point of having to store state so you have something to compare against strikes me as a really odd choice for the React-Reason library to introduce, since it deviates from the functionality of React itself.

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 :).

Re:ReasonML – React as first intended by skosch on Thursday May 24, 2018 @01:52PM (#17146481)
No, you're absolutely correct. Coming from two years of React-ing myself, I went down the exact same thought path as you.

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!)

Re:ReasonML – React as first intended by lsadam0 on Friday May 25, 2018 @08:23AM (#17152879)
Ah, +1 for your point about the poor documentation.

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 :)

Re:ReasonML – React as first intended by boyswan on Thursday May 24, 2018 @11:51AM (#17145176)
You forgot the best bit... variants and pattern matching!
Re:ReasonML – React as first intended by skosch on Thursday May 24, 2018 @11:53AM (#17145203)
True! I suppose I'm comparing to Elm mainly.
Re:ReasonML – React as first intended by boyswan on Thursday May 24, 2018 @12:01PM (#17145277)
Also for your issue with deeply nested options, have a look at this

https://medium.com/w3reality/working-with-option-using-maybe...

Re:ReasonML – React as first intended by bam365 on Thursday May 24, 2018 @12:41PM (#17145767)
And if you don't want to implement the option monad yourself, there's the bs-abstract library, which contains a bunch of category theory definitions and implementations. I have gotten a lot of mileage out of it even in the small amount of ReasonML I have written. That plus ppx_let offers a pretty good monadic programming experience.
Re:ReasonML – React as first intended by skosch on Thursday May 24, 2018 @12:56PM (#17145942)
Those are both helpful suggestions, thanks guys. I've looked at some of those blog posts and github threads before but haven't tried it out.

In the end, however, it's more bolted-on pieces that should be part of the language if you ask me.