OCaml for the Masses (2011)
queue.acm.org
queue.acm.org
In early 2000s, as the web was growing to be an application delivery platform, the only practical statically typed language was Java. It didn't have generics or lambdas at the time, and was infested with the sprawl of J2EE. Choosing Ruby/Python over Java was at the time an act of rebellion and a show of technical superiority. To quote pg: "if they wanted Perl or Python programmers, that would be a bit frightening-- that's starting to sound like a company where the technical side, at least, is run by real hackers."
The static type system in Java is object-oriented: the only way to create a type is to create a class. I believe it was limited in abstraction power and everyone attributed it to the rigidity of static types. Java has come a long way since, but the sense that dynamic typing is superior to static types lingers.
But OCaml's static types are a completely different kind of type. There is a kind of "procedural" static typing in Go, C, and to some extent C++ where primitives are typed and you can construct structs and unions without much ceremony. Then there is object-oriented static typing in Java and C#, which traces its origin back to Simula through C++ where types and classes are the same. Then you have functional static types where types are just and only about data. Almost all Typed FP languages use a form of Hindley-Milner inference, support algebraic data types and pattern matching, have generics (they were invented by Milner for ML in 1973), and allows for code organization and encapsulation through modules and opaque types.
Algebraic data types alone is a tool for thought like no other. You'll start reifying concepts that would've otherwise gone implicit in your codebase thanks to ADT. The languages are solid, ecosystems are vibrant but small and that can only be fixed with more people. Come on in, the water is fine!
OOP is a rather wide umbrella of techniques, involving inheritance, abstraction, encapsulation, etc, all of which can be supported in ways very different from the "let's build everything on the concept of classes" approach taken by Java.
I see Elixir (also mentioned in this thread) getting some traction. Like most of the time its success is mainly due to a singular project with a specific application, namely web programming in Phoenix. Just as back then with Ruby and Rails.
Probably F# would be a better candidate for mainstream adoption with a vast .NET ecosystem and the open source release of .NET Core.
The .NET/Microsoft ecosystem is a no-go for a lot of people, and F# doesn't have functors. Being a statically typed language, you don't have something like Ruby's mixins to share code, nor do you have OO's interface inheritance. Functors fill this gap by allowing you to mint new modules out of existing modules, and is a powerful way of achieving modularity. Simon Peyton Jones critiques that while OCaml's modules are very powerful, the power/cost ratio is not very favourable. And it is true - there is a bit of learning curve, but I think it can be eased as the community grows.
For good or for bad, Javascript is the lingua-franca of computing today if adoption is any measure, and anything that goes against its norms face strong downdraft (try getting Ruby+Opal mainstream adoption). But the updraft can be useful (I'm probably the only person on the internet who don't understand React Hooks yet which was announced just a few weeks ago). Reason is Javascript++: the syntax is very close, and it compiles to vanilla JS with great interop with npm. The promise of gradual adoption I think is a good marketing lever. We'll see in a few years.
There is also Elm, which is just so good for building rich web applications on the browser. It is a language with wonderful aesthetics, clear long-term vision, and avoids importing the complexity of academic research, which is often the case in other typed functional languages.
But you don't really need to pick a language more than you pick Typed FP. F#, Haskell, and PureScript are great as well - each has different tradeoffs. But once you understand the set of features underpinning Typed FP you can move around languages with relative ease, and that's what I think matters most.
a very strong claim. There is a lot of 'computing' outside the browser.
lingua franca of front end web dev, I grant you, (almost by definition 'front end web dev' is mostly javascript).
Why? It's not 2005 - 2009 anymore, when there was this Mono push in Linux-land (remember Banshee? :) ).
Reason seems interesting and I'm glad they shed some of the OCaml syntactic baggage to make it more programmer ergonomic, but it's very unlikely that it'll ever take off. Typescript already has the statically-typed JS market share, and that won't change.
Once Web assembly becomes a mainstream, viable thing, I think we'll see a couple new languages come out that don't have the baggage of legacy like OCaml or Javascript, and could possibly flourish.
Mainstream picks languages based on use cases, not the other way around.
But you do, though. You have open object types, and you can write generic functions in terms of those types, which effectively serves as interfaces (or traits) in other languages.
It is 100% the same?
No, but it is pretty close for practical purposes.
I know having mutability the default still lets one shoot themselves in the foot (and nullable reference types), but I'm always impressed when I find more of the nice FP ideas baked into the language. It's a pretty good compromise for me.
Java 8 was a joy to work with as well - FP is filtering down through lambdas and map, filter, fold et al.
And on anonymous methods (delegates), Func< > and Action< >, that there's even a difference between the 3 shows C#'s age and some of its quirks.
> now tuples and pattern matching in C# 7
Note the pattern matching in C# is a far cry from what you get normally in FP languages. First of all C# does not have ADTs, which means it cannot do exhaustiveness checking, making pattern matching only a superficial syntactic sugar.
Tuples are nice though.
> academic functional programming world and presented them in a nice 'friendly' form
This is sort of a marketing myth. C# is not an FP language and I rarely see actual FP built in C# (same goes for Java).
In my opinion you should try out the languages in the "academic functional programming world". Because you'll then notice that C#'s way of doing things is not "friendly", unless by that you mean half baked and annoying ;-)
This will never happen till there is a typed FP language that has solid tooling, documentation, solid libraries for most common programmer tasks, a welcoming and active community and at least one of a killer app, or framework (Rails for ruby), killer platform (objective c/swift for AppStore dev) or targets an underserved domain (Julia for Scientific Computing).
The existing typed FP language implementations (OCaml, Haskell, SML, not sure of F#) are full of cruft and/or are just lacking with respect to one or more of the above.
Haskell comes the closest I think, but that maybe because I've been using Haskell for decades, and so I am biased in its favor (and I'd still hesitate before using it on a large team + long timescale project).
Try writing a 'mainstream' application in any of the above, and you'll see what I mean. Yes you can write a typical web app /CRUD app/mobile app in (say) Haskell, but to be honest, Yesod (say) is no Rails.
Reason might be 'the one' I guess, at least in bringing TypedFP to the javascript ecosystem, especially with FB's corporate backing.
Rust gets/is getting most of the above right, but it isn't really an FP language.
OCaml or Haskell being the mainstream will never happen imho. If there is a TypedFP mainstream language in the future, it is yet to be invented (or is being invented right now! touch wood).
What is more likely to happen is some FP features moving into mainstream languages. Not sure if that counts as "typed FP becoming mainstream", but it likely to be a long wait ;-)
I honestly don't see any typed FP language ever having the success of say, Python, for at least a few decades yet.
(all imho, ymmv, as it should)
I'm all for new languages! If I remember correctly, the ideal one is Lispy with Hygienic macros, ML-like type system baked in, multi-core, good stdlib, and tools that don't stand in your way.
I'll make a 1000$, 10 year bet with you that in 2028, if browsers still exist, ReasonML (or its successors) will be nowhere near mainstream status (which is the point we are discussing here). I like Reason, or at least the idea of it.
Javascript itself might incorporate more static typing in 2028 than today's version does, but I suggest the 'advances' will be relatively miniscule.
We're not going to see any language supplant JavaScript in the browser. Dart got nowhere, and that was with the backing of Google. But there are already toolkits out there that compile down to JavaScript. GWT, for instance.
Never say never (again. With apologies to Ian Fleming). Just because Dart couldn't do it (even with Google), doesn't mean that nothing else can. I, for one, hope something better does supplant JS.
Nik Graf has a free ReasonML course on Egghead.io, which has a lot of positive reviews from the community. https://egghead.io/courses/get-started-with-reason
Dr. Axel Rauschmayer has written "Exploring ReasonML and functional programming" which covers the language comprehensively. http://reasonmlhub.com/exploring-reasonml/
Web Development with ReasonML by J. David Eisenberg, published by Pragmatic Bookshelfis in the works. I read a few sample chapters and they're excellent for beginners: https://pragprog.com/book/reasonml/web-development-with-reas...
Jane Street wrote a set of 24 runnable exercises that teaches OCaml, and we ported it to ReasonML. It has been used for workshops and individual study and will get you upto speed on the paradigm quickly. https://github.com/protoship/learn-reasonml-workshop
You also have textbooks on OCaml, a lot of them openly accessible, including the venerable Real World OCaml. They are all listed in the awesome-ocaml repository: https://github.com/rizo/awesome-ocaml#books
There is vramana's awesome-reasonml repository that covers similar ground for Reason itself: https://github.com/vramana/awesome-reasonml
Believe it or not, it's even worse if you want to target native code and not JS.
It's an improvement over plain JS, but also a nightmare. For example, it's hard to create truly immutable classes. I ended up with this pattern:
class Foo {
#props
constructor(props) {
this.#props = Map(props)
}
get someField() {
return this.#props.get('someField')
}
withSomeField(value) {
return new Foo(this.#props.set('someField', value))
}
}
It works, but it's annoying. Then you have, as you say, all the coercion/conversions between Immutable and plain JS values.TypeScript would help, but I think I'm going to look into Reason, too. I think I heard that it supports interoperating with ordinary JS. The problem with TS, last I tried it, was that while it supports JS, there are subtleties (like the lack of support for default imports) that mean it's not fully backwards compatible. You can't just run a JS codebase with the TS compiler and expect it to work, as I understand it.
That said, it doesn't seem to have taken off, and it doesn't really look like it will. Not sure why, though I hear a lot of complaints about compile speeds.
my hypothesis (and it is only that) is that trying to unite FP and OO, as Scala tries to do, leads to unnecessary complexity in learning and usage. Also see 'tooling'.
That said, many impressive + widely deployed systems have been built with Scala, which is more than other typed FP languages can claim.
Not sure what "taking off" means in the context of programming languages, but for me it's been popular enough since 2012.
Several big companies use it and I've introduced Scala (and FP in Scala) at about 3 companies thus far ... it isn't a tough sell if the company is Java-friendly.
We also have a great, active community developing libraries. As a shameless plug here are the projects I've been working on:
2. https://github.com/typelevel/cats-effect
Scala is one of the best languages for FP these days. Note I'm not saying that it's perfect. We can certainly improve it and a lot of improvements are coming in Scala 3.
There are add-on libraries like ScalaZ and Cats that are meant to make it easier to follow a more thoroughly functional style, but, even with those, I can't shake the feeling that I'm swimming against the current if I try to take a functional-first approach.
If microsoft would double the budget for tooling support I think it would get there quick, and that wouldn't be a ton of money.
F# isn't properly part of the .NET team, hence only VB.NET and C# get all the goodies.
They didn't even took F# requirements into consideration when doing .NET Native and the whole VS refactorings, leaving the F# team to play catch up on their own.
This is one of the reasons I will dedicate this year's advent of code [1] to learning rust.
[0]: https://science.raphael.poss.name/rust-for-functional-progra... [1]: https://adventofcode.com/
I agree GC free management is necessary, but it should be constrained to certain high performance niches, which cannot cope with GC + value types.
We also had Eiffel, Delphi, VB, Component Pascal, Oberon back then.
But Sun was pumping money and offering the JDK as free beer.
Nevertheless I currently use Python because 1. really great and alive library ecosystem (Pandas, Numpy, Keras and PyQt especially) 2. everybody codes at least some Python, this way whatever I write it is actually going to be hackable by everybody.
I just hope Reason is going to be more successful that F# in going mainstream an will actually replace JavaScript for React developers at least. I also hope an option to force "type hints" (I put them all over the code) is going to be introduced in future versions of Python and Hy language support (Hy is a Lisp over Python, like what Clojure is for Java) is going to be introduced in future versions of PyCharm.
Have you checked https://mypy.readthedocs.io/en/latest/command_line.html#unty... ?
Disagree. This is happening because software development has become an enormous industry, and is now subject to Sturgeon's Law.
If the bulk of software development really was about correctness and quality rather than rapid development and low skill barriers, we'd be seeing a lot more Ada and OCaml, and a lot less JavaScript. But here we are, and it's not going to change just because someone makes a technical breakthrough in the design of functional programming languages.
Better proxies would be Go and Ruby since both occupy the same niches; however, this doesn't support your point as Go has grown much, much faster than Ruby.
The last thing Ocaml needs is mainstream attention. FB's "Reason" being a point in case: "Since I don't understand what I'm doing, can you at least make the syntax look familiar?"
Let the masses stick to writing UX-driven apps in Javascript. It's where the money is anyway, which seems to be the primary motivation for "software engineers" these days.
That's pretty much untrue unless by polish you mean "pretty but pointless IDEs and buzzword/checkbox compliance."
Ocaml is already very accessible, just on its own terms.
> Unix is user-friendly — it's just choosy about who its friends are.
> Anonymous, in The Art of UNIX Programming (2003) by Eric S. Raymond
At the end of the day, each community chooses its path. If Ocaml makes you happy how it is now, more power to you :)
i.e., "ocaml is already very accessible to people who know ocaml"
> If something is truly worth it, it should be accessible to the "masses"
OCaml is accessible to the masses, for 10-20 years already.
I doubt that the masses will switch to FP languages (OCaml, Haskell, Lisp, ...) ever since the classical lightweight languages (Javascript, PHP, ...) provide anything they need for their basic stuff. Only few need more, and they have free choice of several nice niche languages which don't need to become mainstream.
We're here because of mass progress, not because of a few "chosen people". The "great man" theory of history fell by the wayside a one century ago.
What is "mass progress"? There are two options: a) let the masses learn to use the inventions of individualists (which happened with C/C++, PHP and Python for instance), or b) let the inventions be customized to the mediocre capabilities of the masses.
You want option b), obviously. I wouldn't call that "progress".
I would love to see a typed FP equivalent to Go—everything is super simple/small learning curve (I should be able to meaningfully contribute to a project after a day or so), the standard library is decent, package management just works, no guessing about what test lib to use, everything compiles to a single static binary by default (dead simple deployments), no-fuss documentation generation, great concurrency/parallelism story, straightforward profiling and optimizations (e.g., if my program is slow because I’m allocating too much in the hot path I can trivially preallocate), etc. These are the things that matter for real world projects—mathematically elegant type systems really are just gravy, which is why Go has been able to be so successful in spite of its flat-footed type system.^1
^1: if you go over to r/programming, no one can figure this out because everyone believes you can’t ship Software in a language without monads or generics, so Go’s popularity must be due to Google marketing.
Red is another language that is or was striving for simplicity (or resisting the complexity that seems to be the norm in tech nowadays). In fact that was supposed to be one of its main goals. I felt sad when they went down the ICO route for funding, though.
Not sure how FP-ish Red is, though. Rebol, which Red is based on, is supposed to be homoiconic. I like Rebol and Red.
The size of the Rebol and Red interpeters (and Red is a compiler too) and the size of the Red EXEs are quite small, which is another plus. Much smaller than some other languages.
I should say, sometimes seemingly unnecessary complexity.
Is it really so. I am only asking. A mathematical model allows deeper insight on structure (backed by hundreds of years of prior mathematical thought), and we then sugar it appropriately for users. Just like civil engineers who learn Strength of Materials etc mathematically before they design the bridges we drive over daily.
Tooling is one of my gripes also. There was a time decades ago when I couldn't go beyond compiling the simple hello world example. This has gotten much better after many years. Same with Haskell. Is this due to difficulties in getting the necessary financial support.
OCaml less so, but the Jane Street monoculture means that, if it's not itchy for a trading firm, it's not gotta get scratched. Trading's an odd industry, tech-wise. There are aspects of the OCaml ecosystem that eliminate any of my own desire to use the language that I would have seen as neutral or even strongly positive when I worked at a trading firm. (At least during working hours.)
So, yeah, I do think that one of the big things that's missing from typed FP right now is a strong language that has similar semantics to an ML or (preferably) Haskell, but with a much more pragmatic focus. F# is really nice if .NET is an option for you, but I'd sure like to see something that is statically compiled and can produce C-friendly binaries, so that it can play nice with a wider variety of pre-existing codebases.
As for compilation time, Go compilers use very basic optimizations as such they tend to compile faster, but hardly impressive for those that ever used TP, C++ Builder, Delphi, Modula-2 and similar languages.
Can you give some examples? Really curious.
I'm guessing 8-bit strings is a minor positive, on the basis that you really don't need to deal with non-ASCII text in that kind of setting, and there's probably some performance benefit to not supporting it. Even if you stick to characters from 7-bit ASCII in your own data, if the strings are technically UTF-8 or UTF-16, then the fact that it's a variable-length encoding means that more string operations will involve costly branch instructions. And if UTF-32, your strings will be 4x as big as they need to be.
Not working on non-Unix is neutral. There's no benefit to it, but nothing was going to be running on Windows, anyway, so there'd have been no harm in it, either.
I've seen a number of projects (often in JavaScript or Python) fail because of poor effect management—but if you don't have much experience with functional programming, you'd see it as yet another project failing because of bad development practices or lack of discipline.
With experience, it became pretty clear that what we needed were not iron-willed, self-disciplined developers but just better tools, of which effect management (ie monads) and functional programming are some of the most powerful.
In any case, it's a far cry from `go build`.
What does this mean?
[0] https://crystal-lang.org/docs/syntax_and_semantics/blocks_an...
[1] https://docs.microsoft.com/en-us/dotnet/csharp/programming-g...
I've played with it a bit, haven't seen problems with compile times, they were actually pretty good.
The nice thing about Crystal is that it is extremely easy to use, terse code, easy macros, fast executables, algebraic types, good packaging story - in general very good ergonomy.
I hope it'll pick up one day.
[0] https://crystal-lang.org/docs/syntax_and_semantics/literals/...
[Edit: I'd add a few things to your feature list: really fast, OCaml-speed compilation, along with a utop-like REPL]
Why is it not? Hadn't heard of this point before. Is it because of catering to the most common use cases, which are not fine-grained, maybe?
I wish the EXE/binary sizes of Go programs were smaller, though I know they've done some work on that too. Coming from a C background originally, I was a bit surprised when I first saw that the size of a simple hello-world-style Go binary was ~1 MB (some years ago). Equivalent Free Pascal and D binaries are a lot smaller, IIRC, from what I tested at the time (~100 KB or less). Heck, the Red interpreter / compiler (and the Rebol interpreter before it) fit in ~1 MB. Don't mean to denigrate the efforts of the Go team at all (even apart from the fact that as a long-time Unix guy, Rob Pike, Ken Thompson, et al are among the people I look up to); I know language translation technology is a hard field, plus the scope of Go may be much more than that of Rebol / Red; just speaking from the POV of a user, hoping for smaller binary sizes.
AFAICT that's a compiler optimization, not a runtime optimization. But yes, generally the Go team is working to improve performance.
> I wish the EXE/binary sizes of Go programs were smaller, though I know they've done some work on that too. Coming from a C background originally, I was a bit surprised when I first saw that the size of a simple hello-world-style Go binary was ~1 MB (some years ago). Equivalent Free Pascal and D binaries are a lot smaller, IIRC, from what I tested at the time (~100 KB or less). Heck, the Red interpreter / compiler (and the Rebol interpreter before it) fit in ~1 MB. Don't mean to denigrate the efforts of the Go team at all (even apart from the fact that as a long-time Unix guy, Rob Pike, Ken Thompson, et al are among the people I look up to); I know language translation technology is a hard field, plus the scope of Go may be much more than that of Rebol / Red; just speaking from the POV of a user, hoping for smaller binary sizes.
Go binaries contain _everything_, while C programs (usually) statically link against libc (glibc is on the order of 10mb by itself). Go's runtime is also quite a lot more complex than C's--it comes with a scheduler, a reflection system, and a garbage collector. These are one-time costs--the binary for a program 10 times the size of hello world is pretty much the same size as the hello world binary. If you really want, you can dynamically link a Go program, but I can't imagine a scenario where this is practical.
Right, it is a compile time one.
>Go binaries contain _everything_, while C programs (usually) statically link against libc (glibc is on the order of 10mb by itself).
Did you mean "dynamically" (for C) [1]? Also, I'm not too sure if Go links all dependencies statically by default, if that is what you implied above. IIRC I read somewhere recently that some things are linked statically, and some dynamically - I need to check that.
[1] I need to check it for C too, because things have changed since I last used C a lot.
>Go's runtime is also quite a lot more complex than C's--it comes with a scheduler, a reflection system, and a garbage collector. These are one-time costs--the binary for a program 10 times the size of hello world is pretty much the same size as the hello world binary.
Agreed on the points about the other stuff Go has that C does not, like a GC, reflection, etc. And that those are one-time costs. But they are still costs, and if you create lots of small binaries, that cost adds up. Disk space is cheap nowadays, but depending on the use case and your environment (e.g. small or embedded system, cost constraints if shipping many copies of a h/w + s/w product or appliance, etc., that cost might be significant. Whereas with some of those other languages that I mentioned above, those costs can be quite a bit less, times the number of copies of binary or appliance that you ship. That's all that I meant. That's not to say that we should not use Go, though, of course. As always, the overall picture and all factors need to be taken into account, e.g. the benefits of Go's language features vs. some of those others, team knowledge of the various language contenders, even availability of needed libraries, time to market, etc. etc.
Update: Found this page which seems to make sense:
Yeah, I did. Good catch.
> Also, I'm not too sure if Go links all dependencies statically by default, if that is what you implied above. IIRC I read somewhere recently that some things are linked statically, and some dynamically - I need to check that.
By default, Go does dynamically link to some things--it will prefer to use the system DNS resolver if one is available, for example. But you can disable this by setting `CGO_ENABLED=0` at compile time. If you do this, a Go program needs nothing more than a linux kernel (no system libraries or even libc) and whatever other files it requires (certificates, for SSL for example).
> I need to check it for C too, because things have changed since I last used C a lot.
I'm sure you can make statically-linked C programs which are smaller. For example, the musl libc implementation is quite small and designed for static linkage. But lots of libraries break (often in bizarre and hard-to-debug ways) if they don't link against glibc specifically, so it's not a panacea.
> But they are still costs, and if you create lots of small binaries, that cost adds up. Disk space is cheap nowadays, but depending on the use case and your environment (e.g. small or embedded system, cost constraints if shipping many copies of a h/w + s/w product or appliance, etc., that cost might be significant.
Agreed, but again, Go does allow for dynamic linkage in those cases so you can conserve disk space. There's no doubt that if you're golfing, C allows for smaller binaries than Go, but Go can meet 99.9% of real-world requirements when it comes to size (if you're at the extreme end of what Go can support, you've probably already ruled out Go for other reasons).
There are still many reasons to pick other languages besides Go--if you're working on a hard real-time system, if you're working with a team of people who all prefer a different language, if you're working in a domain (iOS app dev, for example) for which there are no good Go libraries, if you're willing to trade all else for extreme performance or extreme correctness, etc. But Go is actually a pretty good little language for most things that aren't at those extremes.
Ah, sounds similar to what it says in the osso.nl link I posted below. Good to know.
>I'm sure you can make statically-linked C programs which are smaller. For example, the musl libc implementation is quite small and designed for static linkage. But lots of libraries break (often in bizarre and hard-to-debug ways) if they don't link against glibc specifically, so it's not a panacea.
Didn't know this, interesting. But actually, I didn't mean making statically-linked C programs smaller by using leaner libraries like musl. I just meant that for equivalent code, the resulting C binary (even when using the default libc) was smaller by a lot than the Go binary. And so were the Free Pascal and D binaries smaller than the Go binary, but they were both slightly larger than the C binary. But it was only an anecdotal observation based on writing a few small programs in C, Go, Free Pascal, and D, and comparing the resulting binary sizes. Not a thorough scientific study.
>Agreed, but again, Go does allow for dynamic linkage in those cases so you can conserve disk space.
Got it.
>>There's no doubt that if you're golfing, C allows for smaller binaries than Go, but Go can meet 99.9% of real-world requirements when it comes to size (if you're at the extreme end of what Go can support, you've probably already ruled out Go for other reasons).
It wasn't about golfing, it was about equivalent code in the two languages, and the relative sizes of the resulting binaries. But good last point (about 'other reasons').
>There are still many reasons to pick other languages besides Go--if you're working on a hard real-time system, if you're working with a team of people who all prefer a different language, if you're working in a domain (iOS app dev, for example) for which there are no good Go libraries, if you're willing to trade all else for extreme performance or extreme correctness, etc. But Go is actually a pretty good little language for most things that aren't at those extremes.
Agreed. In that sense it is somewhat like Python, which is sometimes described as "the second-best language for almost any domain", an interesting description that I read only somewhat recently. I wouldn't necessarily fully agree with that description, it is probably the best language or at least equally the best (with some other language) for certain areas. Similarly, there are probably areas where Go is, if not the best language, one of the best, for certain kinds of tasks, such as the command-line utilities, web and network server applications that it is often used for.
The features are there, 90% of the cases it doesn't matter for the typical use cases.
When it does matter, they are in reach to any savy Haskell developer.
I find that after roughly two years of writing Rust, I can architect and re-architect big projects fairly clearly, and the type system gives me strong reassurances that refactors haven't screwed things up.
Not to mention the advantage of even simple things like enums, which most languages (including Go) tend to lack.
You’d use the “new type pattern”, which is like a named 1-tuple:
struct FirstName(String);You could write your own string parameterized in this way, but it would be incompatible with the standard library String and so you’d need the same conversion steps.
However, for compilation errors, feedback is instant, because cargo check (which runs everything except codegen) is almost instantaneous. I've also set up neovim to give run it on every save (via a plugin), so I don't have to leave my editor for this. I know that VS Code and IntelliJ also do this.
Millions of little decisions with respect to which lifetimes to use, which types to use, which type of pointer to use, whether to pass by ref or by copy, and so on.
> I find that after roughly two years of writing Rust, I can architect and re-architect big projects fairly clearly, and the type system gives me strong reassurances that refactors haven't screwed things up.
> Not to mention the advantage of even simple things like enums, which most languages (including Go) tend to lack.
I don't doubt it. I think these are really cool properties of Rust. They just don't pay for the cognitive burden, since the applications I write aren't critical systems (I can afford _some_ unsafety, but I can't afford to slow my development process).
To put it differently, if I write in Go, I can quickly ship a feature with a high degree of confidence that it's overwhelmingly correct, and the few errors that do slip into production can be quickly fixed because I can iterate so quickly. If I write in Go, I will eventually ship a feature with a very high degree of confidence that it's overwhelmingly correct, but even if I find zero bugs in production, the time spent shipping the first iteration in Rust is much larger than the time it would spend me to ship _and_ iterate on bugfixes in Go. I'm sure the extent to which this is true shrinks as I get more experience with Rust, but there's a law of diminishing returns at play, and no indication that the gap will ever vanish entirely.
Not much of a rebellion, it was just that back then you had instant access to Python's REPL by just typing "python" in any Linux distro terminal. A Python "program" could have been just a simple script_that_does_stuff.py file run from the same terminal with:
> python script_that_does_stuff.py
On the other hand Java was a total mess.
Source: me, a Python programmer for 13+ years who directly referenced this (famous at the time) "Python is not Java" blog post [1] during my first interview for a programmer job
A few thoughts, since some things have changed since that post was written:
First, the tooling limitations that I mentioned in the article have gotten a lot better. In particular:
Merlin now provides IDE-like functionality for your editor of choice (including code, vim, and emacs).
Also, Dune is an excellent build system for OCaml that does an enormous amount to simplify the build process, and tie a bunch of different tools in the ecosystem together. One great thing about Dune is it does a lot to unify the experience we've long had inside of Jane Street with the open-source OCaml experience. It's really a big upgrade.
We've also made some progress on debugging tools, like the spacetime allocation profiler. There's also active work on making GDB/LLDB debugging in OCaml really first class.
Also, OCaml has had some major industrial uptake. Notably, Facebook has several major projects built in OCaml (Hack, Flow, Infer) as well as their own syntactic-skin-plus-tooling on top of OCaml, in the form of Reason. Reason has gotten a lot of traction in the webdev world, which is awesome. Bloomberg, and Docker are some other big names that have real dependencies on OCaml, along with some more names you probably don't know like Ahrefs, LexiFi, and SimCorp.
People sometimes feel like Jane Street is the only real user of OCaml, so they imagine that Jane Street's needs are the ones that drive the language priorities. So, the thinking goes, if you're not a trading firm, you should look elsewhere. But this is the wrong picture. First, there are other serious users, as discussed above. Besides, the community doesn't just roll over and do what we say. If you don't believe it, go and see how often our PRs to OCaml get rejected.
And even our interests in the language have grown beyond what you might imagine a trading firm would care about. We use OCaml for building traditional UNIX system software, like MTAs, for designing hardware (via HardCaml), and for building dynamic browser-based applications (via Incr_dom).
For sure, there are still challenges of being a minority language (and there's still no multicore GC, despite some exciting progress). But I believe OCaml is a yet better choice than it was in 2011 when I wrote the article.
I'm not unhappy at all with the choices I've made so far, but my goals in life are changing and it's making me wonder what it takes to be accepted into companies like Jane Street.
Skill wise I think I'd have to start as a junior developer, which I don't mind, but perhaps having 4-5 years of working experience would disqualify me for those entry level roles?
https://www.janestreet.com/join-jane-street/apply/ldn/full-t...
The answer to this should be placed more prominently on the website, imho.
There is a fantastic web framework called Phoenix built in Elixir. This provides a way that you can immediately build something useful, and it teaches you how to use Elixir well: the documentation is good, the generated code that you start working with is a great example of how to use the language properly, and when you start understanding the design of the framework it's a great example of functional systems design (e.g. the Plug.Conn structure that gets passed around).
Not having to deal with a full ML (or Haskell) like type system takes away a large barrier to entry, but you still have to change your mindset about how you implement things. And then the dialyzer is there, when you later want to start using gradual typing.
I'd say the type system isn't that much of a barrier to entry. You're likely used to one from any existing statically typed language; the only new things are sum types, polymorphic types & type inference. These aren't _that_ hard to get your head round but really improve the safety of your program.
The debate on static vs dynamic is a far from settled one, but I think you would be hard pressed make the case that Python has no place. In this case, I'm suggesting that Elixir is a great way of getting people into functional programming and learning the value, while being immensely useful in its own right.
Learning that value is a good first step. I now find it immensely depressing every time I go from my Phoenix web-app back to the Android app. Kotlin is better than Java, but it's still a mess of objects and interfaces, and having to construct 5 things when it could just be passing a map to a function. The result is that I will now more aggressively pursue FP options when I'm looking at technology decisions (e.g. bucklescript is on my 'to investigate' list).
I see your argument. If your aim is to get into functional programming then Elixir/Erlang, even Lisp/Scheme is fine. I don't think it's the functional nature of OCaml and Haskell that make them powerful; I think those parts of the language are great, yes, but the type system (static, algebraic, inferred) is the real secret sauce.
They may be “simple” in that they are very analyzable but you’re teaching a whole bag of skills, and the most FP part of lisp/scheme is just the closure.
Try to learn Erlang or Ocaml, it's fun.
I really, really want to do my next project in Ocaml, but... I find the ecosystem seriously lacking. You find Ocaml libs for a lot of needs, but a lot of those a unmaintained and have their last commit a couple of years ago. I'm afraid that choosing Ocaml would mean spending quite some time on libraries I need, and less on the app I want to develop.
There's F# and the SAFE stack, but I don't feel home there. A lot of docs/libs still are (or have quirks due to having been) Windows specific, and joining the most popular f# community communication channels requires you to join the F# Software Foundation....
Then there's Scala, with functional programming and access to Java's ecosystem. But I prefer the ML style of Ocaml and F#.
Not sure what issues you ran into, but this isn't necessarily a bad thing. I had a similar experience with Elixir, where some libraries had been last touched two years ago, but did the job with no issues whatsoever.
I have the feeling I encounter a lot of these situations when I look at libraries I would need for a project. It's rather uncommon I see a very active project in Ocaml (even if there are some indeed).
The desire for libraries that are constantly in flux stems from the “move fast and break things” mentality, mixed with the continuous flow of breakage in mutable languages. If you move slow and do things well, you can often build some reliable with a fraction of the effort.
Besides, the language has became quite complex: Monad-based concurrency and error handling, functors, objects, GADT, PPX... it's cool from a language point of view, but as a developer it can get overwhelming. You don't have to used all of this in your project, but still you may have to deal with existing code that is quite complex.
> it's cool from a language point of view, but as a developer it can get overwhelming
If you consider OCaml's features overwhelming why don't you consider a much simpler language (Typescript etc.)?
I am learning OCaml myself right now, and I only use the features which I currently need. If I need more I will learn OCaml's suitable features then. Btw. I like OCaml, after having tested Haskell for a while. OCaml feels like a really practical usable "Haskell light". The compilation speed is outstanding (like LuaJiT).
The only place where I suffer from windows only librairies is UI and graphics in general (I don't do web developement so I cannot comment on that) otherwise developement on linux feels good (first via mono and now dotnet core).
Without the heaviness of dotnet (and, in particular, its project files), it would be perfect.
As remify said F# came from Ocaml : it lacks modules, GADT and other thing but you can easily translate most Ocaml to F#. For me the syntax was a net win.
The thing I miss is the Graphics module of Ocaml's std. I used to build quick visualizations with it and I have not found a good F# equivalent that would run flawlessly on Linux (the relevant section of mono's std was very buggy the last time I tried using it).
Now if I can get away from Ocaml's weird syntax, I think this is still a good deal.
F* is intented for proofs, probably not what you want if you are looking for a general programming language.
Today I say F# is good enough on *nix.
Also doing a little of Rust but the productivity with F# is far higher (you need to ramp up on Rust for a while!)
The repl is not great, even on windows. F# is not the kind of language for a great repl experience, imho. I rarely use the repl anyway (the only one I use regulary is the python one)
It's not an arrangement that inspires confidence - it feels like the community in general really doesn't care about Windows, and it's a few people trying to keep it afloat there - but if they step back, it won't keep.
This mirrors a discussion I've had with my boss a number of times. Most of our products are written in C++, and we complain about how often developers (usually coming from Java) think that everything needs to be inside a class hierarchy. The procedural parts are still there for a reason: the CPU is procedural. A procedure or function is a closer mapping to what the CPU is actually going to do when the code runs.
On the other hand, I've never done serious work with a pure functional language like OCaml. I would welcome the chance, though I wonder if one finds the same kind of dogmatism as in the OOP world...("it must be a pure function!")
Nah, OCaml is a very practical functional language, that's why it features mutable state. You just have to opt-in, so it just encourages [im]mutability as a default, as it should.
Edit: fixed typo!
However, OCaml does not bother you too much (as compared to Haskell for instance) when using side effects like printing.
Ocaml (and SML) aren't particularly dogmatic. They are both eager, so reasoning about performance is much easier. Most things are immutable by default, but you can make mutable data structures in both. Rather than insisting on pure functions, SML and Ocaml allow side effects in functions and have the `unit` type for functions without a return.
The type system is actually strong (eg, no implicit casts) and null exceptions simply do not exist. Multi-threading is the big weakness. Ocaml has been promising support for at least a decade without mainline support. Likewise, most SML variants don't have support (though PolyML does along with a couple others).
Also one can use STRef if they want to have a pure function that is internally implemented with mutable values - that is all the side effects are self contained.
http://gamasutra.com/view/news/169296/Indepth_Functional_pro...
"a function can still be pure even if it calls impure functions, as long as the side effects don't escape the outer function"
As a replacement for C/C++ this makes perfect sense, as a replacement of JS/Ruby/OCaml, not so much.
OCaml has bytecode + native code compiler, both much faster than heavy C++ templated code, or plain Rust code.
I would also say safety/correctness usually win over runtime speed concerns if no other factors are involved as far as Rust design decisions go, at least that’s how it has typically been.
By the way, How is it that HN readers always heavily promote OCaml related threads ?
Because functional is still the flavor of the decade.
Where threads aren't part of the equation, OCaml has become suddenly popular. That's telling.
also the result is still interesting, why wouldn't goroutines scale just as well, but apparently didn't?
IMO OCaml is not any harder than Elm.