Hacker News new | ask | show | jobs
by fsloth 2497 days ago
Can anyone give a pro/cons analysis of a ML variant versus of a Lisp variant. Let's say F# versus Clojure?

One of the general arguments in Lisp vs the world is that lisp is more concise. F# is really concise. It has datastructures as intrinsic part of the language syntax (just like Clojure, i.e in F# [|,,,|] is an array and in Clojure [...] is a vector, so more or less the same thing). Furthermore, the type inferences concierges the developer through the regular bureaucracy involved with strong type systems so effortlessly that you seldom notice it ... unless your code does not compile, in which case it's wrong somewhere and you need to fix it (which you needed to do anyway).

Ok, so for the sake of the argument, let's say the syntax is equally light for F# and Clojure, and their support for immutability is in the same ballpark. And let's remove the argument "a type system is an encumbrance" because that will only lead to situation specific debates - one side will say that massive refactorings are a pita without types, and the other side responds that in Clojure you can use data schemas and should have unit tests anyway. And those discussions never lead anywhere conclusive.

So, besides the above mentioned topics, is there anything general one can say of the distinctive advantages of these two languages in specific situations, including how their two different ecosystems and runtimes affect the calculus?

I suppose it's extremely rare to have experts who have participated in any large scale industrial developments with both of the languages, but if there are, it would be really nice to hear their opinion. And the things I listed as "outside of the discussion" might actually be critical, who knows...

3 comments

My previous startup (CircleCI) was written in Clojure, my current one (Darklang) is written in OCaml. I decided not to use Clojure again because it's not statically typed, and my number one frustration when I coded in the CircleCI codebase was that it was very very hard to know what shape a value had, and whether it could be null.

OCaml certainly has a lot of flaws, and is not nearly as "nice" a language as clojure, but the productivity of static typing (in the statically typed functional language sense, not the C++/Java sense) is huge. Knowing you can do a big refactor and the type system has your back is massive.

We sponsored core.typed to add types to Clojure, but there were flaws at the time (they have have been fixed since), and we didn't end up sticking with it.

So Clojure I wouldn't use again. OCaml I would, despite having significant flaws (every language has significant flaws).

Thanks so much! This was exactly the sort of industrial benchmark I was after.

Am I correct in summarizing your experience as:

The possible encumbrance caused by types at prototyping phase is paid back several times when refactoring a production codebase?

Hmm, I think it's more that types make it possible to refactor without fear, both at the prototyping phase (when you refactor so much, I had 800 lines of python before that that I was afraid to touch) and later.
I have no idea what darklang is (your site has zero information), but what made you opt into OCaml out of all of the options out there? Any previous experience with it prior to this?
Ah, sorry about that. The blog is better at the moment (https://medium.com/darklang) but we're updating the site in the very near future.

OCaml was because I had experience with Haskell and didn't like it, and with Elm, which I did like. We tried it for a while as an experiment and it worked really well.

This whole subhread and this Elm mention are really interesting, thanks. Elm is a frontend language where I really understand the benefits of static more, because you're in a fairly controlled environment and your program isn't talking to a christmas tree of type system defying external services.

But for backend, the benefits of static sound attractive to me only on a program/product that is dominated by its internal business logic and has less interfaces to the unpredictable and constantly changing outside world. I think Darklang may be like this, from looking at the medium.com link?

Ghostwheel to the rescue

(>defn my-fun [a b] [int? -> int?])

I haven't seen anything to like in Clojure spec. Maybe I don't get it, but i really dont get it.
Great question as I'm trying to make that decision myself. I love Lisp in general and the JVM is great and ubiquitous, so Clojure seems good. The reality is that every time I try to learn it, I get stuck learning leinegen, Emacs...etc, which is more than I have to deal with when using Python, so I skip it. Also, it seems like you get a .jar file and have to run it in conjunction with something like "Java -jar clojurefile.clj". I know that isn't too bad, but once I installed F#, I just put the compiler "fsc.exe" and the REPL/interpreter "fsi.exe" in my path and it is pretty simple now. I normally have an fsi window open for testing and write my full code in Notepad++ and then feed that to fsc.exe when I'm done and I get a little executable that is ~5kb. As long as a coworker has the .net runtime on their computer I can give that to them no problem. I'm sure Clojure can do something similar, but as I'm not a Java/JVM person I have no clue how.
For learning Clojure, I highly recommend Oakes' Nightcode Editor/IDE. It integrates Leiningen and Boot, and has everything ready to just code and push "run".

It also intigrates Shaun's awesome Parinfer parentheses management system, which adjusts your parentheses according to your indentation. Think Python rules: Put a thing inside another thing by just tabbing it over.

Thanks! I have the same feeling - the ecosystem with F# feels more robust and production ready. But it might be just because I've never been a Java guy and the things that seem obscure to me in Clojure are trivial to Java people.
I think both are very production worthy as far as reliable code running in production.

Check out the success stories on the Clojure site. One of the biggest ones to me is Walmart using it for Black Friday e-commerce. That is a good indicator to me. They've had good success stories with F# as well, but C# uses F# as a research language and the best bits are kind of bolted back onto C#. It keeps C# as less painful than Java, so less devs make the jump. Honestly, the future for both languages isn't 100% secure. I just wish both languages got more love.

I'm in the same boat as you. Clojure seems to really be meant for someone who already has a few years of Java experience. There are plenty of examples where someone dips into Java and I'm totally lost.

You don't actually need to know anything about Java to be productive in Clojure. At least that was my own experience.
I've been told that before and respect your experience even if it is very different than mine.

Let's talk about writing code in Python. You write a script and either run it through your IDE or via the command line via Python pythonscript.py. With D, I write some code and feed it through the compiler like dmd scriptname.d.

With Clojure in addition to all the cruft I have to learn (Emacs, leinegen...etc), I still have to know something of Java. One of the big selling points is integration. If I know zero Java, how am I supposed to make use of the various classes? Even if I largely stick to just Clojure, how does one interpret the Java stack traces? What is the best method for running via the JVM? How do I performance tune the JVM? How do I use GUI frameworks that are largely all OO Java?

You can run Clojure without Leiningen and you definitely do not need to learn emacs. I use vim, but Cursive (IntelliJ plugin) is IMHO the most beginner friendly option available (other good options include Nightlight, Atom with clojure olugin, VS Code with plugin). You can run Clojure without learning Leiningen with many of these too.
Honestly ml feels like typed (basic) lisp excluding parenthesis.

So I think it does come down to if you like static types or not.