In summary, Reason [2] is a new language (correction: interface to OCaml) that shares a part of the OCaml compiler toolchain and runtime. I don't know of any language that uses a similar approach, that is, plugging into an existing compiler toolchain. I guess a reasonable yet inaccurate analogy would be Reason -> OCaml is like Elixir -> Erlang or Clojure -> Java.
I hope Reason can provide OCaml with the extra push needed to bring it into the mainstream PL space and more widespread adoption.
> The OCaml compiler is organized into several stages, which are exposed as libraries. Reason replaces part of the compiler toolchain with a completely new syntax parser that is more approachable, while still fully compatible with the rest of the compiler. Reason also implements a new source printer which integrates into your IDE and the new custom REPL.
So you can abstract the syntax from the runtime, but the semantics are often different per target - e.g. accessing the filesystem in Node.js will be different to C++, due to the non-blocking I/O mechanism.
As an aside, the Haxe compiler is written in OCaml. I think there'd be a delicious juxtaposition if it was re-written in Reason. Writing Reason to generate OCaml to create Haxe to generate Java to generate bytecode...
It should be easy to convert the Haxe compiler into Reason with refmt. Maybe unless if it's using camlp4 syntax extension... But I guess you could add a camlp4 pass before running refmt.
Sure, OCaml isn't even the nicest syntax in the ML family, but I'm not sure whether that's worth it, especially considering that almost any "X-like" language often turns out to be an Uncanny Valley for "X" programmers -- close enough to make some frustrating errors.
I've mentioned elsewhere that the primary goal for now was to get the tooling automated as much as possible, so that when we receive common feedback, we can adapt to that feedback and trivially migrate people's code forward.
I don't think JavaScript's syntax is a selling point and I am someone with a lot of JavaScript experience. I also don't think that OCaml's syntax today is a selling point, and I have a bit of OCaml experience. Both of these syntaxes have evolved over time, working within that limited precious syntactic real estate, trying so very hard to maintain compatibility with decisions made decades ago. Reason's approach is totally different in that it knows we won't get it right on the first shot so it puts into place the tooling for upgrading and beautifying as we learn lessons and take feedback from the community. It places the syntax closer to the user, even if only conceptually.
That being said, the current syntax is not intended to be a JavaScript clone by any means. It actually started in the opposite manner - by taking the top 15 complaints about OCaml's syntax, by experienced OCaml programmers (not JS programmers) and fixing them. There were a couple of things that didn't really matter (such as how you express comments) that were just changed to be more familiar because, well.. simply they don't matter, and even experienced OCaml developers want the largest possible set of people to be able to read their code as long as that comes with little other tradeoffs.
But an advantage I see with the new comment syntax is that there are is that there is no ambiguity what the hell (*) is. At least this.
Maybe that's because it's the first and only thing one can see and therefore it's cheap to have an opinion? Or is it because too many professionals are used to languages which are little more than a syntax on top of a toy evaluator?
When I first try ocaml long ago, I though overcoming the syntax would be a huge challenge (especially since I was using lisp at the time). Surprisingly, I got used to it after the first night, and even started to like it. Just a single data point of course, but it seems useful to warn new programmers that your first impressions on the syntax of a language are just that. Also, your estimation of the time that would be required to learn a new language based on how easily you can parse the syntax at first sight is completely wrong. It took me longer to understand some error messages that the compiler threw at me long after I though I could "speak ocaml" than to build an initial understanding of the syntax (roughly 2 hours).
All of the above, of course, is just a disgruntled and grumpy way to say: despite we all know we don't care about the syntax of any language once we know it, it's still an overly important factor to drive a language adoption (or, in the case of ocaml, disaffection). Therefore, let's hope this new "revised syntax" will help many more programmers discover more sophisticated languages than the industry standards!
Under "Why OCaml?" on the Reason page, it states, "OCaml has a very mature (and still growing) ecosystem for targeting browser and JavaScript environments with a focus on language interoperability and integration with existing JavaScript code," and "Reason‘s non-invasive approach to the OCaml compiler allows Reason code to take advantage of all of the existing OCaml compiler optimizations/backends such as ... and even JavaScript compilation."
It seems like what's being said is that one of the main goals for Reason is to integrate with JavaScript, and it would seem to make sense instead of changing between language syntaxes, you'd want more in common between them, so it makes sense why they are similar. I'm confused as to why you seem to be trying to distance Reason and OCaml from JavaScript, when it definitely seems like the similarity with and integration with JavaScript would be a driving factor in Reason's development now, even if maybe it wasn't in the beginning.
Reason seems really cool, btw.
EDIT: Hosting a Meetup this friday at 6pm in San Francisco about Reason and how to instantly start using it, http://www.meetup.com/sv-ocaml/events/231198788/
No, this is not a silly notion. But I don't think the difference Reason makes is as big as you think. I mean, I don't really believe that you can read this:
let foo = if (cond) { x } else { y };
foo + 1
but not this: let foo = if cond then x else y
in
foo + 1Not sure why the Reason syntax isn't more like F# though.
I'm finally going to switch away from my ancient nvi setup and use Atom instead! MirageOS recently moved all our libraries over to using the new PPX extension point mechanism in OCaml instead of the Camlp4 extensible grammar. This means that MirageOS libraries should be compatible with Reason out of the box -- so it'll be possible to build unikernels from a slick editor interface quite soon hopefully!
What's OCaml's status with multithreading? Are there any proposals for more flexible operators, so there doesn't need to be different operators for different numerics? (F# solves this by allowing inlined functions.)
BTW, one thing that I do find awkward about Ocaml's syntax is the difference between := and <-. Dunno if its possible to unify them in a sane manner though.
I know syntax is subjective, but some of the choices seem a bit odd. For example, declaring variants and using their constructors looks like Haskell, but the semantics is still OCaml. In Haskell, constructors are first order so they can be passed as functions, and partially applied. It makes sense that their declaration and use looks like function declaration and function calls. In OCaml they are not first class, that is, you can't pass the as arguments, or partially apply them. That's why it makes sense for the declaration to look like a tuple, and the use to look like a function applied to a tuple--well, somewhat, you can still argue that it's still confusing because you might expect to be able to apply the constructor to a tuple variable, but well, such is life :). Unless constructors are first class in Reason--it doesn't look like it from a quick scan through the docs--this particular syntactic difference is of dubious value, and, worse, it can be misleading to newcomers.
Also, changing `match` to `switch` seems gratuitous as well, and it also loses some of the meaning of the original. i.e. "I want to match this value against this set of patterns".
Finally, I know that using `begin` and `end` for blocks is verbose and Pascal-ish--which people seem to hate for some reason--but using { } for scopes looks out of place, and leads to awkward cases like this:
try { ... } { | Exn => ... };
I don't mean for this to sound ranty, or like I'm picking on Reason. I think it's good that facebook is tryiog to spice things up in the OCaml community.If I understand what you're saying, you provided a reason why variant arguments should not look like function application (because they have different semantics than function application), and then in the same paragraph suggested that variant arguments should have tuple syntax, while admitting that they don't actually have tuple semantics either.
The truth is that variant arguments in `Reason` actually do not have function application syntax - note the distinguishing, leading capitalized letter on the variant. Sure, they share the fact that arguments are specified via a space separated list, but function application doesn't have a monopoly on the syntactic pattern of things separated by spaces. The argument quickly breaks down.
But I guess in Reason they could be first class. All it takes is to interpret an occurrence of an n-ary constructor
Foo
as (fun a1 ... an => Foo a1 ... an) @media (min-width: 1180px) {
body:not(.no-literate) .content-root {
background-color: #fdfcfc;
-webkit-box-shadow: inset 780px 0 #fff, inset 781px 0 #e7e7e7, inset 790px 0 3px -10px rgba(0,0,0,0.05);
box-shadow: inset 780px 0 #fff, inset 781px 0 #e7e7e7, inset 790px 0 3px -10px rgba(0,0,0,0.05);
}
}
Removing it in the Firefox style editor restores normal performance.Edit: And they have commented out the box-shadow! Hah.
Checked this out, but the reason still eludes me: https://ocaml.io/w/Blog:News/A_new_Reason_for_OCaml (pun intended)
OCaml can also be compiled to JavaScript, like pretty much every language can these days.
Having worked with Reason, JavaScript, and the bridge between the two, most of my errors seem to fall on the JavaScript side. So I guess the type system's indeed working =).
EDIT: and they want to use and maintain compatibility with ppx. Great news
You can even upgrade your existing OCaml source code to be in the Reason style by using the versatile `refmt` program that is included.
https://codeboard.io/projects/17520?view=2.1
Of course, you can also create your own Reason projects.
The point of the syntax toolchain is actually not to get it right on the first try but to make something viable that is easier to learn/read, avoid bike-shedding, and put all the right tooling in place so that we can very seamlessly upgrade after taking in feedback. It's pretty liberating to know you have that ability to move forward rapidly and automate all of the upgrades.
Is there any interactive functionality that your website offers that would justify extraordinary demands or does it simply display some text and images?
I agree with you but one benefit of `fun` is that it aligns better with multiples of two spaces. It's important when lists end up wrapping:
/* Nice multiple of two spaces */
fun myFun
xyz
abc => {
doSomeThings(xyz, abc);
};
/* yikes, only one horizontal space between
* doSomething and abc on the line above */
fn myFun
xyz
abc => {
doSomeThings(xyz, abc);
};
I'm obviously no stranger to bike-shedding! let (|>) x f = f x let (|>) x f = "%apply"
which utilises some language magic and is probably faster.If they can simplify the build system to be on par with something like cargo that would be swell.
Also: having rust style traits or haskell classes would be amazing. Also macros that aren't obscure and hard to use compiler plugins please :)
Hopefully it ends up being more than just questionable sugar around ocaml and actually adds some sorely needed language features.
- Teaching new programmers how to use ML, and OCaml in particular.
- Keeping consistent formatting rules among a large team or project and automating that within your editor.
- Benefiting from the comprehensive pattern matching checks provided by the OCaml compiler.
- Benefiting from faster compile times of `ocamlc`, or faster native execution time of `ocamlopt`.
- Benefiting from Merlin, and the new version of Merlin with support for Reason - I cannot overstate how important Merlin is to my daily development.
Soon:
- Having conventions for forming namespaces within packages.
- Making it easier to share and connect many small packages into a a larger application, and develop those packages locally.
- Having "just works" support for the REPL, so that it's one fast command to start the REPL with all your dependencies loaded and autocomplete would just work.
- Having a "just works" debugger loader that maps all of your source files and compiled artifacts so you can instantly start debugging your app.
It's been a while, but taking a look at this comparison of SML and OCaml again:
http://www.mpi-sws.org/~rossberg/sml-vs-ocaml.html
It feels a bit like you've landed in some strange neither-or space for Reason? I'm not sure if it would make sense to bend OCaml into being a subset of SML or not (I know there are some differences, just not sure how much those require different syntax, or if they do) - but did you consider moving more toward SML?
I can see the reasoning between going from <> to != and <- to = (there are more programming languages, and more programmers now, than ever before, and whatever the merits of using = for comparison, almost all other languages in common use now have it as an assignment operator (even if it is still a source of bugs a la: "if(a=0) ...")).
It's exiting times with Elixir and Lisp Flavoured Erlang for Erlang, and now Reason for OCaml (and to some extent various dialects, languages and DSLs for Javascript, like typescript, coffee script and JSX for React).
- No IDE, I was happily using Vim but many of my coworkers were using Emacs. What helped a lot was Merlin, so I could print the types of the identifiers. This was much more useful than any REPL or IDE I have ever used.
- Debuggers: didn't use much, ocamldebug was an okay experience at best
- Linters: did not use. Most of the LOC were simple enough to just be obvious.
- Deployment: it was a Makefile which took about a minute to build the compiler from scratch. I guess that by using a proper OCaml build system we could've sped things up by requiring less recompilation but it was fine. In the end a binary fell out and could be used however.
I liked the development experience a lot, once it compiled it was reasonably clear that it would work as expected, expanding the compiler was very nice since every time I added a new variant, the compiler complained where I need to add code and then it just worked. We had the advantage that we already had our own mini standard library, so most missing utility functions were already in place when I joined.
I imagine an hlint like linter might be useful, and could give you information about common programming patterns. (Ie hlint tells you when you could be using foldr instead of an explicit recursion.)
For me, the development experience is pretty good. But it takes some time to get used to this new world. Conventions are not the same.
I think the only complains we can do at the moment are the switch from '<-' to '=' for mutable records and from '->' to '=>' for functions. But we will see how it will evolve
The comma placement suggests that developer is an adjective for experience.
- OCaml compiler's stdlib: http://kcsrk.info/reason_stdlib_docs/index.html
- Batteries: http://kcsrk.info/reason_batteries_docs/index.html
So, why do I want to learn this, rather than, say, Go or Elixir?
http://ocsigen.org/lwt/2.5.1/manual/
Also, for parallelism, elsewhere in this thread this link was shared:
Also, what's a convincing concurrency story? Does multiprogramming count?
A version of OCaml offering a similar "concurrency story" would have a lot of appeal.
- Type system -> OCaml is more modern (despite being designed before Go)
- Concurrency, parallelism, garbage collector, tooling -> Go is more modern (Reason is improving the tooling with refmt for example; work is ongoing on parallelism)
I don't really see most of the changes as improvements.
Having a different, explicitly-noticeable syntax for mutable updates is nice, because it calls out mutability (which should be used sparingly).
I don't see extra braces as necessarily an improvement, given that OCaml's local scopes are already quite unambiguous thanks to "let ... in". On that note, Removing "in" and just going with semicolons removes another "smelly-code-callout" by making it less obvious what's imperative and what's functional.
I actually don't like ambiguity between type annotation and value assignment in my records. It's clear in current OCaml that {a: int} is a type declaration and {a = 1} is a value declaration/assignment. Moving to colons-for-record-values is at best a bikesheddy, backwards-incompatible change for change's sake, and at worst a breaking-change way of code less clear.
Speaking of making code less clear, how is "int list list" not clear? It's an int-list list. As in, a list of int-lists. So of course it should parse as "(int list) list". Why change to backwards annotations? Just to prevent existing code from working as-is, and making people used to reading ML spend extra brain cycles on remembering that your types read the opposite way?
And they make a huge deal out of their type for tuples being "(a, b)" instead of "(a * b)". Yeah, okay, I get it. It's not that big a deal, since people are used to reading product types as, well, products.
The other thing that seems weird to me is the need to change to a "fat arrow" instead of a "skinny arrow", again for no real reason. In fact, it just makes it more likely that you'll confuse it with a comparison operator. Nobody tries to type ">-", but people try to type ">=" all the time. You're just switching for the sake of switching, and it's not an improvement.
Their example code of their replacement for match...with is especially egregious. If you showed me the OCaml snippet and the Reason snippet unlabelled, I would think that the OCaml snippet is the new-and-improved version, since it's much more compact, much less noisy, and reads more like what it's trying to do ("match my_variable with either SomeValue x or SomeOtherValue y").
Another thing they make a lot of noise about is requiring fewer parens in some places. But then, they also require more parens in other places. So...okay? I guess? Not really a win.
And why rename equality operators? Are you really going to tell me that people prefer that their languages have "==="?
This is actually an improvement in my opinion. Reusing the syntax for function application in type application makes the language more uniform. It's even necessary with dependent types.
A lot of the better changes reminds me of the revised syntax http://caml.inria.fr/pub/docs/manual-camlp4/manual007.html
(why would you introduce the ternary operator when if-then-else is so much nicer to read?!)
It seems like Reason is solving a non-problem. When I first went to the webpage, and saw "Build Systems Rapidly", I thought maybe it was a new build system for OCaml. I was hoping it would be a Cargo-style build system/package manager for OCaml.
This is for those people who do not like OCaml because of those warts. If you are one who is already sold on OCaml, it's very easy to forget how many there really are.
Regarding "Build Systems Rapidly": Please hang in there and stay tuned. The syntax is there to help people learn ML rapidly. The Merlin integration and syntax formatting tooling is there to help people become productive rapidly inside their editors. Next, we have specified a workflow for actually building systems rapidly (as in compiling large projects with namespacing rules).
Instead of our previous approach where we just drop a more polished project with many of the goals accomplished, this kind of project benefits from expertise that is distributed across the entire industry and for that, it's better to be open earlier. I hope you can appreciate and encourage this kind of openness.
Wild guess: Due to moving to a brace syntax for blocks and '=' for assignments, they needed to move to colons to disambiguate something that already used braces and '='. That is, something like this:
let x = ref 0;
type record = { x: int };
if (cond) { x = 1 } else { x = 2 }
might read either as creating a new record value or as writing throught the reference. (Again, just a guess.)EDIT: All that said, I agree with you. OCaml's syntax is meh, but moving it closer to brace languages makes it worse, not better. Some of these changes actually move closer to Haskell (constructors without parens, yay!), and those are the changes I like.
For example, when you're using C++, be sure to rewrite the string and stream classes (like Folly does). This will ensure that you can't contribute anything back to the community, and they can't contribute to you. Be sure to use all the funny C++ features that haven't quite been standardized or supported correctly yet.
For OCaml, it's harder, since it doesn't have as many poorly designed and duplicative features. But with enough effort, you too can fix the "problem" of your code being similar to other people's code.
Documentation suggestion: add examples for string manipulation.
Edit: just doesn't load at all on Edge. Does load in Chrome/Opera and surprisingly IE 12 but doesn't load the logo's font.
| List p (List p2 (List p3 rest)) => false /* 3+ */
has the regular list destructuring in pattern match syntax been removed? that's pretty sad, if so - lists are the default data structure in ocaml, and it's worth retaining some special syntax for cons especially in pattern matches.When so much of your code is function calls, all those commas and parenthesis start cluttering things.
Don't let my complains about syntax deter you, this looks like a very exciting project!
Edit: The fix came quickly though.
In particular Rust has similar syntax, seems to have all Reason's features plus the linear types and regions/borrowing that allow memory and concurrency safety while still being able to mutate memory and not being forced to use GC.
They are aware of Rust since they cite it in their page, so I wonder why they decided to create this instead of using Rust.
It would be nice if they explained this in the FAQ.
I guess it might be useful if you have an OCaml codebase to interface with but don't already know OCaml, but given the relative obscurity of OCaml that seems a pretty narrow use (and also Facebook isn't known to make extensive use of it, afaik).
Use rust when you need the performance. Use a GC'd language like reason when you want less things to reason about.
I would say Rust trades more predictable performance for a more complicated borrow system.
REPL is quite nice for programmer productivity.