Hacker News new | comments | show | ask | jobs | submit login
Announcing BuckleScript 1.0 (bloomberg.github.io)
323 points by e_d_g_a_r on Aug 31, 2016 | hide | past | web | favorite | 75 comments



I'm on the Facebook Reason team, and we're using BuckleScript to compile OCaml into the best compiler output I've ever seen. People didn't recognize that my React components were generated, not hand-written.

BuckleScript's author (hongbo_zhang here) has been incredibly responsive and welcoming.

We'll be publishing the React.js binding on HN in a few days. Stay tuned! We (including Hongbo) are all sitting in irc #reasonml and https://gitter.im/facebook/reason


Reason describes itself as "a meta language toolchain to build systems rapidly", which seems a little vague to me. Am I understanding correctly that Reason is both a (kind of) alternative compiler for OCaml's build toolchain, and a dialect of OCaml in its own right?

To tie this back to Bucklescript, does this loosely describe the process of using Reason syntax to author Javascript? Reason file -> (Reason) -> OCaml executable code -> (Bucklescript) -> Javascript


If you'll forgive the shameless plug, I talked a bit about ReasonML here, hopefully it helps clear things up https://youtu.be/QWfHrbSqnB0?t=29m34s

Basically, just a new syntax and a blessed-stack approach that really, really emphasizes developer experience. Which is to say, ReasonML is merely a cosmetic and DX change, it remains compatible and is not a fork of OCaml at all.


Thanks, that's very helpful!


Think Elixir for Erlang.

Currently it's a syntax on top of OCaml. But we'd like to polish the OCaml ecosystem tooling too; we're calling the umbrella project "Reason".


That will be great. Ocaml is great language, but not that user friendly.

Elixir is pretty mature nowadays. Reason still have a long way to go. Hope that will happen.


> Currently it's a syntax on top of OCaml.

Does this just mean it compiles to OCaml?


There's a crucial distinction! OCaml's compilation command takes in a `-pp` flag (preprocessor), which accepts a command that takes in a file and outputs an OCaml AST tree. We're basically using that. In that sense, the official OCaml syntax is really just that: another syntax like Reason, but official, and goes back two decades.

Because of the clean mapping from one syntax to another, you can toggle between the two fairly easily: https://github.com/facebook/reason/wiki/Newcomer-Tips-&-Tric...


Interesting. Thanks for explaining that.


Pretty cool that BuckleScript works with Reason! :-)


> We'll be publishing the React.js binding on HN in a few days.

Sounds great. Will this be announced on any email list I could subscribe to? Thanks!


No email list for now. We'll be active in the chat rooms and HN though.


Will you integrate with React Native?


I am one of the authors of BuckleScript, you can try BuckleScript in the browser: http://bloomberg.github.io/bucklescript/js-demo/

Click Examples see how the JS code generated, questions are welcome!


I just wanted to say thanks to the authors of Bucklescript. Not sure if I'll ever get to use it in a production system, but definitely awesome tech. I played with it a little bit and I think an OCaml React app might actually compile faster than the same thing written in ES6 and compiled/built through the normal babel+webpack toolchain.


you should checkout reason, they are working on bindings using bucklescript. So it is not a dream, people probably can write react app using ocaml very soon


Hey, so when Ocaml comes out with modular implicits (hopefully soon!), will they be supported? If I recall correctly, Bucklescript is compiling Ocaml source, as opposed to Ocaml bytecode like js_of_ocaml does [this is incorrect, see below]. Assuming this is the case, I'd guess the downside is you have to specifically work to support potentially complex new features like modular implicits.

I think between modular implicits[0], multicore support (both coming soon), along with BuckleScript and js_of_ocaml, Ocaml will be the functional language to beat in the coming years.

0. For those unfamiliar with modular implicits (Scala has them), they are kind of like type classes, so we won't have to write things like "print_string" or "print_int" anymore; we can just write "print".

Edit: NEvermind, I see you're compiling the lambda IR. So hopefully support for modular implicits will be automatic!


> I think between modular implicits[0], multicore support (both coming soon), along with BuckleScript and js_of_ocaml, Ocaml will be the functional language to beat in the coming years.

Since you mentioned Scala ... you realize Scala has had those properties for years, don't you?


Yes, true. I'm probably overstating things. Just excited about the prospect of having these things in Ocaml. Scala is an impressive language but it's a big language. I prefer the relative simplicity of Ocaml and (even more) SML.

Also, performance-wise, with multicore and the new optimizations with flambda, Ocaml will be particularly interesting.


we still reuse ocaml's compiler tool chain. we are compiling ocaml's lambda into JS. so yes, we will support modular implicit once it is landed


Thanks for this! Really awesome stuff!

One question here: how tight the compiler is binded to OCaml semantics? Besides Reason, do you think it's possible to build a frontend for other languages and integrate the backend of BuckleScript to generate beautiful JS as well? Or in other words, what property do you think a language should have so we can generate this level of beautiful JS outputs?

BTW: Please understand I'm not objecting OCaml, I do believe OCaml is an awesome language, but my point is: if possible, we should make this beautiful backend for generating human-readable JS more accessible than restricting it to OCaml only, shouldn't we :)


OCaml compiler is designed in an extremely modular style. Actually you can design any syntax for OCaml (including lisp style) and produce the OCaml data structure, then it should work with BuckleScript, that's how Reason works


Are there internal projects inside Bloomberg that use this? It is really great and it is very impressive that it seems that you almost single-handedly did all this. I am curious what moved Bloomberg to start a project like this.


we have an intern this summer create bindings for our internal JS stack. we have some internal stuff running on server side in OCaml which we wish to move to client side. I would say many thanks to my boss and employer's great support


BTW, congratulations on the 1.0 milestone!

How did you become so proficient with the OCaml compiler internals? When you started the project did you already know that you can compile to idiomatic js or was that discovered through experimentation?


Thanks! I have some experience in ocaml compiler internals, I reimplemented camlp4 called Fan. Yes, I made a prototype in 2 weekends and showed it to my boss and got very good feedback


Very neat. Can BuckleScript compile Core?


It would have to be Core_kernel, the subset of Core that doesn't interact with the runtime or OS. I'm very curious about this and would like to know, too.


If you want to use the OCaml ecosystem, use js_of_ocaml. It has much better compatibility and there is no perf difference.

In particular, js_of_ocaml works with both core_kernel and async_kernel.


Indeed, js_of_ocaml is kind of shocking in its fidelity. It can compile even highly complex libraries that do lots of runtime tricks. Async_kernel and Incremental_kernel both compiled and worked without any issues whatsoever.

We've even built some support for making incrementally rendered web-apps in OCaml, using Async and Incremental. Here's a link:

https://github.com/janestreet/incr_dom

It sounds like Bucklescript is doing something quite different, which is to aim for pretty JavaScript output, while compromising and maintaining semantic consistency with OCaml. I don't fully understand the use-case, but for us, js-of-ocaml is clearly the thing we want.


as long as it is vanilla OCaml (no c stubs), it should be fine


Uh, given that you don't respect ocaml's memory model and force -safe-string, that's just not true. Any Obj.magic that is correct in OCaml is probably not going to be correct in bucklescript.

Did you actually tried to compile core ?


`-safe-string` is the future. Any compiler can not guarantee its correctness if you write crazy code , `Obj.magic` here. I am not interested in core personally, but I don't see any reason why it will not work if it is vanilla OCaml


This is really cool! I took some OCaml code I'd written a while ago and pasted it in and the output was shockingly legible even with the calls to functions in stuff like Caml_int32 and Pervasives. Very impressive!


From a practical standpoint, what's the difference between js_of_ocaml?


much more readable transpiled output, really nice (and getting nicer) FFI to javascript. but it doesn't interface with existing ocaml stuff as well (doesn't use `.cmo/.cma` so it needs to compile everything from source afaict)


People gave you the part in favor of bucklescript, so I'll give you the other side of the story:

bucklescript doesn't respect the OCaml memory model and runtime semantics, which makes it incompatible with some part of the ecosystem.

Js_of_ocaml already has various features that bucklescript doesn't have: dynlink, support for concurrency libraries such as lwt and async, etc. It's also much more stable and battle-tested.


to be precise, Js_of_ocaml does not respect OCaml memory model either, think about float. But I think Js_of_ocaml is really great, BuckleScript and Js_of_ocaml have different use cases.


it is generate more readable JS. and we have spent lots of time in polishing the FFI to make OCaml/JS interaction easier


I've been following Bucklescript's development from the sidelines for the last couple of months along with Facebook's Reason (https://facebook.github.io/reason/javaScriptCompared.html).

I'm very optimistic about the future of these two projects. Both are working hard to build a soundly-typed platform on top of the JS ecosystem. While there are tons of existing languages that can be compiled to JS, the most successful ones are those (like Typescript) that embrace the npm ecosystem and the huge community investment it represents.

Both Bucklescript and Reason have a huge focus on seamless JS interop and DX, and stand a good chance of bringing soundly-typed functional programming to a much wider audience!


I was wondering about the practical differences between BuckleScript and js_of_ocaml. Found this brief explanation in the docs[0]:

> Js_of_ocaml takes lowlevel bytecode from OCaml compiler, BuckleScript takes the highlevel rawlambda representation from OCaml compiler

I presume that means different (higher-level) optimisations are available in BuckleScript?

> Js_of_ocaml focuses more on existing OCaml eco-system(opam) while BuckleScript’s major goal is to target npm

Now that is a good idea—npm is a fairly large ecosystem that people are already familiar with. If you haven’t already, you might look into using existing TypeScript interface files to get type information for npm libraries.

> Js_of_ocaml and BuckleScript have slightly different runtime encoding in several places, for example, BuckleScript encodes OCaml Array as JS Array while js_of_ocaml requires its index 0 to be of value 0.

Would it ever be feasible to support interop with js_of_ocaml?

[0]: http://bloomberg.github.io/bucklescript/Manual.html#_compari...


yes, it is actually easier to optimize since you have more herusitics. both compiled to js, so yes, it can work together : )


This is one of the few JS compiled languages that interest me: Some of these languages add a very thin syntactic layer on Javascript and maybe a type system. If I wanted Javascript, I'd use Javascript, and if I wanted types, I'd use Flow, not a new programming language that's kinda-sorta-not-really JS.

That leaves this, Clojurescript, and SPOCK as the only really interesting projects. They all have runtimes that are unpleasantly large (well, Buckle may not), but that's the price of a new language.

However, Clojurescript leaves a bad taste in my mouth, and SPOCK stresses javascript implementations in interesting ways. I'm not really a fan of OCaml, but Buckle looks interesting, and more enjoyable/practical than the other two.


I bet you heard about Elm and purescript?


Forgot about those. Yeah, they're on the list. Elm seems to be the most practical of the lot, and also one of the nicest to program in.


I've been using Elm for the last 2 weeks on a project and I love it. I still get slapped around all the time by the compiler, but at least I know my program won't have any run-time exceptions.


If you like Elm, you will like Buckle too! we have a much faster compiler, and you can compile it into native code as a bonus : )


Took more than 10 seconds to find this link:

http://wiki.call-cc.org/eggref/4/spock


I've been meaning to get into ClojureScript. Can you elaborate on why it leaves a bad taste in your mouth?


Well, first off, I don't really like Java or the JVM. That in itself is a pretty strong reason to not get into Clojure.

Secondly, I don't really like Clojure as a language: It's strongly opinionated, and made some unorthodox (for a lisp) design choices which I dislike.

Finally, Clojurescript is really heavyweight, dragging along not only its own runtime, but also the google closure library and compiler, making the entire system more complex than it needed to be (was there any reason we needed to have a closure dependancy?).

Don't get me wrong, Clojure isn't an objectively bad language, it's just a language I personally dislike. If you have similar tastes to me, you may not like it either. OTOH, You may thibk it's The Best Thing Since Sliced Bread (TM). That's fine, I just won't agree.


Not an expert, but having dabbled in cljs, I think this misrepresents it. The closure dependency makes things arguably heavier at dev time, but at compile time it allows for a lot of dead code elimination and other optimization that makes the actual output much more light weight. It doesn't slow down development, but allows for a much better product to be deployed.


Fair enough. However, as I've mentioned, there are other reasons I dislike clojure.


redhat's ceylon looks good too: http://ceylon-lang.org/


I guess... but it's advertising to large teams, it seems java-oriented (so if I wanted that sort of thing, I could use Clojure), it's pushing an IDE, and it's from Red Hat, a company that has given us such marvellous technologies as networkmanager, rpm, dbus, systemtap, and systemd - so while not an awful track record, not exactly picking all winners either.

All in all, kind of neat, but that is just way too many red flags for me to say I'm bursting with anticipation to use it.


agreed about the red flags, but the actual language looks very tastefully designed and pleasant to use.


I suppose. But I'm not really the target audience: I'm more comfortable in Scheme than Haskell, and I'm willing to forgive JS most of its warts (especially since it's got proper HOF (better than Python and Ruby, anyways), and is getting TCO. It even has a macro system, courtesy of sweet.js (even if it is only a limited pattern-matching one, as opposed to the imperative systems of Lisp and most Schemes)).


I've just started learning OCaml. Bucklescript as well as F* and Reason are the reasons I chose OCaml over F#

https://www.fstar-lang.org/


do you have any uses in mind for F*? i went through the tutorial a while ago, and it looked very nice, but i couldn't think of anything i wanted/needed to use it for.


Eventually I would like to write a C Compiler with it


Here's a talk the BuckleScript author recently gave on it.

https://www.youtube.com/watch?v=LC3KKHYbSQQ


Very cool!

I'm surprised by this one:

https://bloomberg.github.io/bucklescript/js-demo/#Curry_Opti...

Why doesn't it actually curry? Impressive output, don't get me wrong. But given how native and idiomatic currying is in Javascript, and how much trouble I'd expect this to have taken to implement... is there a specific reason for this? Just curious.

Anyway, again: very impressive. Thanks.

EDIT clarification: I expected:

    function f(param) {
        return curry(32, param);
    }
(or is this to highlight the difference between currying and partial function application?)


Looks like it's just an optimization. If you change to

  let test_curry x  y =  x + y + x
You get the expected output

  function f(param) {
    return test_curry(32, param);
  }


btw, we also have native uncurried calling convention support to make callback even more efficient


It looks like tail call optimization only works in simple situations.

    let rec foo i = if i < 0 then "foo" else bar (i - 1)
    and bar i = if i < 0 then "bar" else foo (i - 1)

    function foo(i) {
      if (i < 0) {
        return "foo";
      }
      else {
        return bar(i - 1 | 0);
      }
    }
    
    function bar(i) {
      if (i < 0) {
        return "bar";
      }
      else {
        return foo(i - 1 | 0);
      }
    }
It would be nice to get a warning when tail calls cannot be optimized.


yes, we will have this warning when upgraded into OCaml 4.04 Note that optimizing mutual recursive call is a very hard problem it needs VM level support


Mutual tail call optimization requires VM level support in general but can be accomplished within a compiliation unit (module) via inlining.


Seems like it should also be possible to have the compiler employ JavaScript generator functions (i.e. `yield`) and iteration as a substitute for growing the stack, which might be a bit more flexible than rewriting in terms of loops+thunks, though the concept is the same.


OCaml seems to be on an upswing in popularity/hype recently. As someone who's threading the waters in Clojure but not a fan of the JVM developer experience I'm curious why OCaml is a great choice.

I would love to hear some stories from people using it in production. I'm leaning towards wanting to use a LISP as it's just so elegant... but I feel that getting boggled down in "hard core" functional programming is a bit daunting and limiting.


I'm in the same mindset right now. Really like aspects of Clojurescript and its elegant syntax, but it's complicated machinery (JVM, Google Closure) make me wary. I'm sure they're well done, but because I'm mainly interested in the JS target, I'm open to something like Bucklescript, along with Elm, Purescript.


Since it has a significant overlap with Fable (https://fable-compiler.github.io/), a comparison would be interesting.


The website says BuckleScript can also be compiled into a unikernel, which links to MirageOS. I get the sense that integration between MirageOS unikernels and the javascript Bucklscript compiles down to is a likely usage-case scenario?


Previously called OCamlScript? The GitHub link at https://news.ycombinator.com/item?id=10860815 now goes to Buckle.


yes, it has a conflict with existing project, so it was renamed later


This looks really cool. How does the integration with external JavaScript libraries work? Could I use this with something like Three.js?


Definitely, almost half the time is spent in polishing the FFI. Check out the FFI section in the Manual. OCaml's type system is so powerful, that it can model most js libraries without writing JS stubs code




Applications are open for YC Winter 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: