Why Bucklescript?

Bucklescript homepage | Our wiki on it
Elm homepage | Our wiki on it

Why? :icon_twisted:

Seriously, what does it offer that Elm and all the other current options don’t? And I hope it is not whitespace dependent :101: (and ideally not reliant on endless semicolons and brackets as well :lol:)

The elm language was modeled on OCaml and Haskell, most of the syntax comes directly over. ^.^

It can do everything Elm can do, and a great deal more (it is a full language that is older than Erlang).

And nope, not whitespace dependent, Elm has that because of some of its haskall’isms, OCaml does not have that, it is fully expression based, right down to the module level. In Ocaml you can do this if you want:

let myFunc i =
i+42

And it works as you expect, where in Elm that same code (sans the ‘let’ since Elm uses haskell’isms) will give you an error unless you indent the i+42 part. :wink:

Here is the Counter example from Elm put in to OCaml (via my OAK-TEA library, which emulates the Elm API precisely): bucklescript-testing/src/main_counter.ml at master · OvermindDL1/bucklescript-testing · GitHub

Breaking it down:

open Tea.App
open Tea.Html

This is the same as this in Elixir:

import Tea.App
import Tea.Html

It just imports the ‘usage’ of what is in the modules into the namespace so you don’t need to prefix (you can ‘open’ in smaller scopes too if you do not want to open to the entire file, like in Elixir too).

type msg =
  | Increment
  | Decrement
  | Reset
  | Set of int

This is similar to Elm (except in Elm the first Increment cannot have a |, have to put the = instead, which bugs me), it just defines a type, msg in this case, that can have 4 custom names, one of which, the Set one, can also hold an integer. Standard ADT, think of it like this in Elixir (and in fact there is at least one Elixir library that simplifies this for you too):

:Increment # Is the same as the `Increment` in OCaml
:Decrement # Is the same as the `Decrement` in OCaml
:Reset # is the same as the `Reset` in OCaml
{:Set, 42} # is the same as `Set 42` in OCaml

The equivalent of the usual tagged tuples of {:ok, data} and {:error, reason} in Elixir/Erlang is the Result.t type in OCaml, it gives you an Ok data and Error reason variant constructors, as another example, etc… Very generic variant data container, same as tagged tuples in Erlang/Elixir (in fact that is how they would be implemented in an OCaml->Elixir compiler).

let update model = function
  | Increment -> model + 1
  | Decrement -> model - 1
  | Reset -> 0
  | Set v -> v

This defines a function names update, that takes a model and another argument (the function keyword is like a function-level match context, just code simplification, it would be the same as doing let update model message = match message with of the let line, the rest is the same) to match on, would be like this in Elixir:

def update(model, message) do
  case message do
    :Increment -> model + 1
    :Decrement -> model - 1
    :Reset -> 0
    {:set, v} -> v
  end
end

And it is fully type-safe (trying to return an integer, for example, would fail, telling you that it expects an int instead), thus catching lots of programming bugs.

The next set of code:

let view_button title msg =
  button
    [ onClick msg
    ]
    [ text title
    ]

let view model =
  div
    []
    [ span
        [ style "text-weight" "bold" ]
        [ text (string_of_int model) ]
    ; br []
    ; view_button "Increment" Increment
    ; br []
    ; view_button "Decrement" Decrement
    ; br []
    ; view_button "Set to 42" (Set 42)
    ; br []
    ; if model <> 0 then view_button "Reset" Reset else noNode
    ]

This is less OCaml and more Elm, I duplicated the Elm API to a T(EA), it is just building a DOM in javascript via a virtual-dom, same as in Elm, this is the only [] that you find here if you notice. It would be the same as this in Elixir:

def view_button(title, msg) do
  button([
      onClick(msg)
    ], [
      text(title)
    ])
end

def view(model) do
  div([
    ], [
      span([
          style("text-weight", "bold")
        ], [
          text(Integer.to_string(model)
        ]),
      , br([])
      , view_button("Increment", :Increment)
      , br([])
      , view_button("Decrement", :Decrement)
      , br([])
      , view_button("Set to 42", {:Set, 42})
      , br([])
      , if model != 0 do view_button("Reset", :Reset) else noNode()
    ])
end

It is just DOM building, near everything takes lists of attributes and lists of elements, except it looks worse in Elixir (could simplify some things so a br with no arguments implies a [] so br() would work, but eh…).

The last bit of code:

let main =
  beginnerProgram {
    model = 4;
    update;
    view;
  }

Just calls my beginnerProgram thing in my OAK-TEA library, you pass in the callbacks (a default model of 4, the update function, and the view function, you could do those as update = update; and such too, but if the name is already the same it is optional, and yes ; is the list separation operator, same as , in Elixir). The ‘main’ variable is just what I call it, you can call it whatever you want, just elm calls in main and in elm it is forced, where it is optional here, but I still call it the same for the examples. This would be something like this in Elixir:

def main() do
  beginnerProgram(%{
    model: 4,
    update: &update/2,
    view: &view/1
    })
end

But yes, compared to Elm the language is actually well tested and battle-hardened over decades, not changing every major version, still being developed and worked on (a lot actually, more so than erlang), and the semicolons/brackets all depend on what API you are working with, by default it has substantially less than Elm, but with my OAK-TEA API it duplicates that part of Elm too. ^.^

9 Likes

Thank you for the in-depth post ODL1 - you certainly make a compelling case and it’s clear you are very passionate about it (that’s good, because this sort of passion is infectious!) :lol:

I’m going to bookmark this thread and come back to it when I have more time (and when I am ready to start researching front-end properly). In the meantime do you know of any beginners tutorials on Bucklescript?

Also (not sure if you’ve mentioned this before) but there seems to be a striking similarity between some of the Elixir code and the Bucklescript code - does creating an Elixir to Buckelscript transpilier sound like a good idea?

Do you know any big projects using Bucklescript? Better still any apps in production?

Edit: One thing that bothers me; Facebook’s Reason boasts “Friendly Syntax & Toolchain Powered by OCaml” - friendlier than what, Bucklescript? If so does this mean most people will use that instead? :icon_confused:

(PS I hope you don’t mind I split these posts into a new thread as I think the topic may be of interest to a lot of people now and in the future)

1 Like

I hope I can recognize good languages after this time. ^.^
Elm has a fantastic TEA library, but its language kind of sucks, he should have built his library on an existing language.

Grab any on OCaml, one and the same. The official OCaml site has a tutorial section that is decent.

Yes, and it is entirely possible. OCaml has a great FFI system that would work fantastically to integrate with existing Elixir code and all.

Beyond many in OCaml. Bucklescript just hit 1.0, but probably the biggest ‘production’ system is Reason.

The OCaml compiler supports two kinds of extensions, pre-processor extensions, pp, which transform text into text, like if you want to make another language that targets to OCaml, and AST-processor extensions, ppx, which transform AST into ‘something else’, which can be more AST, which allowed you to add features ‘to’ OCaml, or to even take the AST of OCaml and process it out to another language. Bucklescript is just a PPX for the OCaml compiler that plugs itself into the last hook in the PPX system so it takes the optimized AST and outputs to Javascript, an Elixir output is just as possible the same way.

Reason is just a PPX plugged early in the OCaml compiler hooks that just gives OCaml a slightly different syntax. Reason is basically a Javascript’ish syntax on OCaml, but it is still OCaml, like it uses => instead of -> and it uses curly braces everywhere to delimit scope instead of just making everything expressions (like javascript, so it has a ton of curly braces, like javascript). If you know Reason you can pick up OCaml trivially, and vice-versa, there is even a Chrome extension that can auto-convert for you and Reason comes with tools to convert for you too. They are the same AST, same language. It is not even like the difference between Elixir and Erlang, everything about it is the same except a couple minor syntactical differences, it adds nothing over OCaml, no extra features, etc… They are just making it to be a go-between to tempt Javascript programmers to the better OCaml language (their words), but if you already know OCaml, no real point unless you like the changes. Reason and OCaml interoperate perfectly, can be used in the same project, etc…

Consequently, Reason can compile to native code, it also can use Bucklescript to compile to Javascript, it is all just plugs in the OCaml compiler. :slight_smile:

1 Like

Thanks again for the reply ODL :023:

So when would one use Reason or Bucklescript over the other? Reason when they want JS-like syntax and Bucklescript when not? Do either have any other benefits over the other? I.e will Reason have more tools etc? (Therefore more likely to be used than Bucklescript?). I wouldn’t want to use Bucklescript only late to find out that it has lost to Reason : /

Also, why OCaml? What’s so good about it? Where does it fit as a language? What are it’s strengths and where is it used most often?

1 Like

Different things. :slight_smile:

Bucklescript is just a backend to the OCaml compiler that outputs javascript instead of native code.

Reason is just a new syntax that adds on to the OCaml compiler (but you can still use OCaml’s syntax too).

Bucklescript by itself will just compile OCaml to javascript.

Reason by itself will just compile to native code through the OCaml compiler (it is just a plugin to the compiler that lets the compiler understand ‘re’ files in addition to ‘ml’ files).

Reason + Bucklescript will compile reason and ocaml code to javascript.

That can be mixed and matched as you wish.

OCaml has a TON more PPX’s too that can be mixed and matched with the above as well. It is a very powerful compiler, almost trivially easy to extend. Think of PPX’s on the OCaml compiler as being an Elixir-like Macro system on OCaml, except it is even more powerful as it can not only translate ‘other’ code to OCaml, but can also translate OCaml to other things, like javascript. ^.^

It is the current and most advanced incarnation of the old set of (S)ML languages. They are strongly typed, fast to compile, the compiler tries its best to catch as many of your programming issues as it can at compile-time compared to run-time. As an example OCaml can compile at or near the speed of C++, while having substantially shorter and more readable code. ^.^

It is used heavily in a few areas, oddly enough Facebook is a big company that uses it extensively, they’ve released a lot of tools and libraries that were built in OCaml. The biggest user of OCaml is easily JaneStreet though, they’ve practically shaped the entire OCaml ecosystem over the past decade, moving it forward and in to the modern age, that is how OCaml is still so powerful and fast nowadays including giving it the very hex-like opam library manager.

Basically if you want to write in a language that catches most of your programming issues, is dang-fast, and is easy to read and write, that is what OCaml is built for. Optimized C++ can still outperform OCaml sure, but it is within a magnitude of difference, far better than near any other language out that is not something as low-level as C++.

2 Likes

Ahhhhhhhhh right… so basically Bucklescript is an OCaml to Javascript transpilier, and Reason is a new JS-ish language that compiles to OCaml.

Phew! :lol:

In that case Bucklescript and OCaml sound very interesting (totally not interested in Reason). It might be an issue that FB are also putting out OCaml libraries - what kind? Are they essentials or ‘leading’ libraries in OCaml?

Going back to OCaml - what kind of things is it being used for? What might, say, most of us, use it for? Is it faster than Crystal? Go? Rust? (How does it compare to those?)

Sorry for all the questions just trying to get a feel for the language and how/when/why it would be used :smiley:

Nah, Facebook uses OCaml a lot internally, the things they release are like the ‘Flow’ compiler, which is kind of like typescript for javascript but can be progressively added (pretty nice actually), but they’ve not released much in the way of libraries. JaneStreet is where all the big OCaml libraries are. Even Bucklescript is made by Bloomberg. ^.^

Go is about the same speed, cannot do as much in it, Go is also more verbose on average.

Rust is a lot more low-level, more like C++, significantly more verbose but Rust is the same speed as C++ (more or less depending), so anything you can consider for comparisons of C++ work also for Rust. Rust is just a safer C++ it can be considered.

Crystal is another native language, no JS transpiling, it could theoretically get close to C++'s speed over time but it is not there yet, currently slower than OCaml, but theoretically it could get on par to OCaml over time (since OCaml is almost C++'s speed, sometimes faster depending on situation).

The main thing of OCaml is the whole program static typeness, few if any languages are better for programming complex systems, such as compilers. C may have the most compilers written in it, but next is likely OCaml as an example, compilers are ‘hard’ to get right, and compilers written in OCaml are significantly more stable (and often faster) than ones written in C. :wink:

Bucklescript lets you take OCaml’s ability to represent ideas safely and brings it to javascript. This would be as awesome as, say, Rust getting a JS transpiler, instead of just an emscripten cross-compiler that Rust has now, which makes utterly unreadable javascript in comparison, Bucklescript is an OCaml transpiler, where it takes OCaml and outputs readable and fast javascript.

OCaml has an actual javascript compiler called js_of_ocaml, you’ve been able to write OCaml to javascript for a long time, but it made fast but entirely unreadable code. Bucklescript rather outputs readable Javascript from OCaml (as you can demonstrate with on their testing site in real-time). With its full first-class javascript bindings via its FFI interface, that means that OCaml (via Bucklescript) can be intermixed with Java, they can call each other with ease, meaning that you can start a new project with it or introduce it to an existing project with no compatibility worries. :slight_smile:

3 Likes

Thanks again for the reply :slight_smile:

Well, you have certainly put forward a compelling case and I am going to look more deeply into it when I start a new project that might make use of it. I’ll probably want to see a few screencasts or tutorials on how to do everyday things with it to get a proper feel of whether I might get on with it or not, so if you find any more links please add them to the thread.

Also think some of the info here could be added to your Bucklescript wiki? Perhaps even if just that Bucklescript is an OCaml to Javascript transpilier (and with the following benefits…). That could get more people on board as the current thread is quite long and it’s not immediately obvious what Bucklscript actually is.

I am also thinking that this thread should be renamed to ‘Why Bucklescript?’ as that’s what it has become - what do you think?

There are some good points on their blog too:

BuckleScript is an optimizing compiler which compiles OCaml into JavaScript module by module without name mangling. The generated code is highly readable and super small, see the Hello world example and examples of calling JS libraries. BuckleScript is strongly inspired by TypeScript, BabelJS – we consider readability and easy integration with existing JS libraries to be essential.

There are a few things we believe BuckleScript does better than TypeScript:

Generated code is more efficient and fully type-safe

  • BuckleScript is not a new language, it is OCaml. OCaml offers an industrial-strength state-of-the-art type system and provides very strong type inference (i.e. unlike TypeScript, no verbose type annotation is required), which proves invaluable in managing large projects.
  • OCaml’s type system is not just for tooling; it is a sound type system which means it is guaranteed there will be no runtime type errors after type checking. Based on this guarantee, BuckleScript provides many optimizations during offline compilation. You can view a simple benchmark here!

All the benefits of OCaml with a feature rich and efficient Foreign Function Interface (FFI)

  • Your program can be compiled into native code, JavaScript, or even a unikernel. The BuckleScript compiler is expected to become even faster and produce better code due to more and more optimizations in the upstream OCaml compiler.
  • Thanks to OCaml’s native support of the Object structural type system, BuckleScript’s FFI can model JavaScript objects natively. Some powerful type system features like polymorphic variants and GADTs are also invaluable in modeling existing JavaScript libraries.
  • Unlike most language FFIs, the design goal of our FFI is to avoid writing any unsafe JS “stub” code with a performance cost. In particular, we try to avoid any unnecessary memory allocations in the FFI.

Compilation speed is key to a good developer experience

  • Our internal benchmarks show that BuckleScript compiles at least ten times faster than TypeScript. There is no magic here, the BuckleScript compiler is written in OCaml which is compiled to blazing fast native code.
    However, this does not limit the availability of the compiler: it can also be compiled to a JavaScript program (700KB for pure OCaml + 300KB for Reason support).
  • The playground is powered by the compiler compiled to JavaScript, which demonstrates a nearly real-time compilation speed. Imagine how fast the native compiler is!
  • We are pleased to announce a stable 1.0 release of BuckleScript, which covers the whole OCaml language (except some features highly coupled with runtime, like the GC and Unix modules, etc.). To learn more about BuckleScript, please refer to the user manual. We welcome your feedback.

https://www.techatbloomberg.com/blog/bucklescript-1-0-release-arrived

3 Likes

@OvermindDL1 You’re doing great as an evangelist, did you know that? :slight_smile: I’m hooked; installing OCaml and OPAM right now. Will probably try out Bucklescript later.

4 Likes

I hate JS and all it’s “cannot blabla undefined”, but the next thing I’ll look after fpr myself will be OCaml and bucklescript for sure, right after mastering more Elixir. You’re great at evangelization, I have to agree to that :slight_smile:

3 Likes

I like it more after watching some of these:

Hong Zhang seems like a capable and knowledgeable person too :023:

1 Like

It’s not clear to me if you’ve uploaded this somewhere for actual usage or if it’s a one-off. Could you clarify and/or perhaps set up instructions/example projects for 1/2/3 step setup so that one can move straight to using it?

1 Like

Heh, Bucklescript I can see as having staying power, I never saw that with Elm. With Bucklescript people can take the existing substantial OCaml knowledge, libraries, and power, and use it on the front-end.

Yeah the stuff I put is scattered all over, should really put it in a single location…

Lol, probably good, and done I see. ^.^

OCaml is definitely well worth learning even just on its own, fantastic for making native programs that you know will ‘just work’ in addition to learning it will help you in languages elsewhere do to the functional programming it teaches.

I still really badly want an OCaml->Elixir transpiler, that would fix the last bits of annoyances I’d have with Elixir (once my code was ported over). ^.^

Ooo, things to watch! Yep he knows his stuff. He’s been a long time OCaml dev, on the OCaml compiler, lots of projects that used the compiler, etc… He knows his stuff!

Right now it is just in my little bucklescript-testing project on github, you can copy/paste the relevant files into your own project if you want to play with it right now, but I plan to do an actual npm-release with it once Bucklescripts new compiler infrastructure is finished (and I update my bucklescript-brunch module to use it, which is optional for usage but convenient for phoenix-brunch users ^.^). But that is why I do not even have a readme file yet, not wanting to give the impression it is ‘done’, even though it is basically is as it is. I still want to clean up the code as well before release, it has a lot of experimentation in it. :slight_smile:

2 Likes

So whats about a PPX that translates OCaml to Elixir?

This makes it possible to write code in one simple language that compiles into the ErlangVM, native OCaml and Bucklescript JS.

Plus, this idea combines Elixir and Erlang with the strong type checking of OCaml.

OCaml, Reason, Elixir, Erlang and Javascript in one language.

1 Like

Here is, by the way, a full list of differences between Reason and OCaml, pointing out some things which are unnamed in this thread until: https://reasonml.github.io/guide/ocaml/

2 Likes

I’ve considered precisely that, even started a little project to experiment with it. :slight_smile:
In a crunch period at work currently though, so no time to mess with it lately. If someone else wants to do it, please do. ^.^

Precisely my thoughts!!

Oh that would be such bliss… Getting closer to the perfect language for web work…

I have no coding experience and i am still looking after my first language. :wink: [quote=“OvermindDL1, post:19, topic:2319”]
Oh that would be such bliss… Getting closer to the perfect language for web work…
[/quote]

I think even more, since OCaml offers speed, where Elixir is sometimes to slow.

1 Like

If it compiles to elixir there’d be no difference then. ^.^

However making NIF’s and Ports both from OCaml is entirely doable too though, hmm, a unified language for it all, interesting thought…

1 Like