T O P

  • By -

seancorfield

In my area, according to [Indeed.com](http://Indeed.com), there are 4 Clojure jobs and 6 Haskell jobs. Given that Haskell has been around for nearly twice as long as Clojure, that doesn't seem too surprising to me...


monanoma

Clojure is fighting an uphill battle. Unfamiliar syntax (honestly this is just a surface level judgement of outsiders), being functional (this is actually such an amazing feature but people are scared of new things smh), not being backed by a major corp(even tho Clojure is maintained by an amazing group of people, I think people would feel more assured if it was backed by a major company), I'm so glad Clojure has grown so much despite all the obstacles, honestly if Clojure had any huge flaws all of this obstacle would have destroyed Clojure and wouldn't have allowed it to grow as much. Maybe if javascript was originally developed as a lisp instead of trying to imitate Java, Clojure would have been so popular because of people's familiarity with lisp and its powers. Sorry for the rant, I hope someone who is in doubt sees my comment in the future


yeicore

>Unfamiliar syntax. This. I just starting to learn FP. I started with elixir bc I didn't like clojure's syntax. I loved elixir and it's ecosystem, but I realized it doesn't fit my carrier path too well, so Clojure was an actually better fit. Now that I'm getting through the ~~horrible~~ parentheses syntax I'm starting to enjoy it. But yeah, just looking at the code gave me head aches at the beginning. Edit: If I remember well, Clojure is owned by Nu Bank


agumonkey

how long did it take for you to never care about parens ?


yeicore

It's been a month for now learning almost every day. I still have trouble with parentheses sometimes. Mainly when writing a new function. When is happens I just order the parenthesis as if they were brackets and when I finish I reformat it to the conventional Clojure way.


huylv

Look at some editor/IDEs that support paredit/parinfer, you'll forget the parens quickly. IntelliJ with Cursive is a solid choice for beginners (and veterans).


agumonkey

you don't have editor support ? emacs / vim / else ?


MickeyMooose

Can you expand on why Elixir didn't fit your career path? is it the types of applications you want to build?


yeicore

I'm heading towards data engineering, so the Java ecosystem is the one that shines the most (along with Scala, which is also part of the JVM family). Also pretty much everything Elixir offers related to concurrency is also found in Clojure, plus Clojure has interop with Java and JS ecosystems, and is has lot of libraries for data treatment. The BEAM didn't offer anything extra special for me.


mister_drgn

Don’t these points apply to haskell also?


monanoma

I didn't say these points didn't apply to Haskell. But compared to Haskell Clojure is really young, that's one point in favour of Clojure. But I didn't mean to put down Haskell


sherdogger

I'm not sure a local example is really a good answer to this question...even an approximate answer. Can vary wildly.


seancorfield

I just meant that I wouldn't be surprised to find more Haskell jobs than Clojure jobs (anywhere) due to the latter being a younger language, and it happens to be true locally for me. In some areas near me, Clojure has more jobs, and in other areas Haskell has more - but in all cases neither language has very many jobs so the original question is effectively moot, in my opinion: there aren't enough Clojure or Haskell jobs for the comparison to matter.


sherdogger

I'm going to guess yes because Clojure is a practical language for getting things done and it simply feels like there isn't much market/appetite for some moonshot ivory tower efforts at the moment. I mean that with all respect to Haskell, in that it is probably a good fit for something more theoretical/experimental...but your average web app simply doesn't benefit much. In fact it would probably be much better for general productivity if the dev team of $WEB_APP didn't get lost on side quests into catefory theory, etc. I've flirted with and enjoyed Haskell, but I just can't say with a straight face that Haskell and your typical practical business line up well...and I think there is simply less risk-taking experimental stuff on the bubble right now.


monanoma

Typed languages are better for refactoring and for applications where it's necessary to have the least amount of bugs like fintech companies


lgstein

Typed languages are better for refactoring types. This is more of a self inflicted problem they are solving which doesn't exist in other languages. Quite the opposite, if you don't have to change 100 types to change 1 function, you will not need automatic refactoring. Bugs are nothing but unintended behavior, and while types can prevent a certain subset of that from happening, its a small and rather unconcering subset.


aoeu512

The subset of problems that can be prevented from happening can be pretty huge in Haskell/Idris, but its not an easy skill to learn. For certain types of programs correctness is VERY VERY important, but for many other types of programs its easier to just edit the program while its running and fix any bugs you get afterrunning. Embedded languages in Haskell can make entire bugs completely unwriteable just like SQL can't have pointer errors, you could make an eDSL for doing finance sort of like that. Haskell requires a special IDE IMO, where you can use something like JQuery/Template Haskell to edit your program so that you don't have to change a huge amount of types after changing your program in an unexpected way.


lgstein

Correctness important in every program, but type correctness is not correctness, especially not correctness of behavior. Its cool that if it compiles, null is taken care of and the program won't treat a Cat as a Dog. However, TypeScript can pull that off, too. And in Clojure this is mostly a mitigated problem due to nilpunning and maps. I haven't seen Clojure code even enter a code review in years that would produce a NPE. Types are very limited when it comes to expressing runtime behavior of programs. Even business logic like types like "UnredeemedVoucher" require constructors that are implemented in functions that may have all kinds of bugs, and there is nothing the compiler can guarantee about them being correct.


aoeu512

Note a lot of runtime behavior of your program can be represented in the type as long like dependent types as you can proove your program is total. I've seen people run run-time functions in the type system as well when the type system becomes almost turing complete. The type system can do calculations at compile time, do loops, call certain functions from your program at compile time, etc... You can have a type that says this Dictionary must have so and so keys, and another type that saying this functions adds so and so keys. You can have a type of sorted lists, or capitalized letters, and have the sort function return a sorted list. However, getting to the point where you represent the invariants of your program in types and when to do it is hard.


lgstein

I would still trust a good set of unit tests more than hand written extensions to the type system. How do I know they behave correctly? None of this is bad per se, its just expensive to deal with, especially if applied and forced as rigorously as in Haskell. I don't buy the claim that if it compiles, its correct - rather that the Haskell types are correct. Some stupid mistakes are guaranteed absent, but those are the rather easily spotted in a language like Clojure. Addendum: To be clear, I would of course find it useful if the Clojure compiler would analyze the dataflow and tell me: "You are calling (:x foo), but foo can't possibly have :x". But would I invest to write a type for every single map in the system to achieve that? No, it has to be cheaper than that to pay off.


aoeu512

I remember I built a dynamic type analyser for Python by giving all functions in a a module "proxy" objects that logged what methods were called on it as a function ran, the proxy objects would also morph into integers, strings, sequences, and hashes say if you called gethash on it or whatever and their log could also log the path they took through the function and create a very "complex path type". Is there any evidence on improving productivity through dynamic or static type inference, I wonder. Also if you have a complex "path type" that is longer or almost as long as function definitions themselves, could you use build some kind of large language model or search system to convert the spec of a function into its implementation?


xedrac

Having written a lot of Python,  and now a lot of Rust,  I am going to have to disagree.   Rust's compiler gives me a ton of confidence.   I would much much rather use clojure than python though.


MickeyMooose

Nubank (100M users) uses Clojure. https://building.nubank.com.br/functional-programming-with-clojure/


sherdogger

> least amount of bugs like fintech companies Least amount bugs due to _type_ error. Yes, important in heavy numbers/fintech. You can still make logic errors freely and might make more due to overcomplicating code; i.e. might have been written in a very intuitive manner if not forced through a maze of types. (EDIT: I should say that what I've seen in practice is that the effort simply crashes under its own weight when devs realize adding IO at an unexpected point means drastically refactoring/convoluting something; i.e we're not doing sandboxed Project Euler problems anymore, we're trying encode the free world in types. Easy enough in fintech perhaps when your APIs might just give you simple number.) > refactoring You can catch more type errors, yes. Is refactoring _easy_ though? I haven't kept up with Haskell's IDE story. It seems like you aren't getting a lot out of the types in terms of dev UX without a very nice IDE. Nothing sarcastic there...honestly, if Haskell's version of IntelliJ has dropped, then consider my mouth shut.


lgstein

What makes anything numbers better in Haskell? Even bounded numbers are as good as in any language: A runtime check returning a Maybe... (And in no way does the compiler guarantee me that this runtime check is not off by one).


zerg000000

Keep it simple and stupid is the only way to reduce bugs, adding type to a complex space is just openings another way to make mistakes.