Live data from Hacker News

Six years of professional Clojure development

falkoriemenschneider.de

51–60 of 209 posts

Re: Six years of professional Clojure development

#51
post #6

Nice article. Sadly a lot of people won't even try clojure since it is dynamic typed. I see their point but nevertheless clojure does something really well here. As the author obserserves designing around some core data structures results in high code reuse. A library like spec is also way better in encoding business requirements than all the mainstream language typesystems e.g. a number in business context has mostl…

Can we have a REPL-driven language that's statically typed? My hope is yes, in that it's just that the work hasn't been put in yet to create to create the equivalent of Typescript for Clojure or Lua that compiles down to the actual, extensible language. I always wish that it would become unnecessary to have to choose between stability and extensibility when selecting a programming language. Having a Clojure with stat…

There's always Common Lisp using the popular SBCL implementation. It's not statically typed but you still get compiler warnings about types at compile time -- even cooler is that SBCL uses the types for assembly code optimization, so it can also guide you to write faster code with type warnings, e.g. about places where it couldn't infer the type and is forced to use a generic addition.

https://news.ycombinator.com/item?id=14780381 shows a few errors that provide typo protection, no type declaring needed

https://news.ycombinator.com/item?id=13389287 shows the optimization warnings

https://news.ycombinator.com/item?id=12222404 shows it can even delete unused code thanks to type inference

There's also a handful of attempts to bring stricter type checking guarantees on top as a library, but I haven't experimented with those. I'm very much in the crowd that doesn't find static types very valuable (apart from aiding performance) even for multi-million-line projects, but if I can get a few non-strict warnings like SBCL gives, that's a nice bonus, much like running a concurrent linter for extra warnings in .

I liked Clojure a lot, but fell out of love once I realized how much it's still missing from the Common Lisp it was inspired from (non-bonkers OOP, condition system, and reader macros being the biggest to me), and also how its pervasive laziness is something I'd rather opt in to than vice versa. Some people feel the same about its immutability-by-default structures, I don't mind either way. (e.g. I can opt in to them in CL, that's fine, and Clojure's ways of opting out of them aren't bad either.)

Re: Six years of professional Clojure development

#52

Earlier quoted context omitted.

I don’t think it’s the parents, but the s-expression themselves. LISPs forces you to maintain the stack for the parse tree in your head, something humans aren’t that great at — s-expressions are the programming language equivalent of center embedding, which is quite alien for human languages (the depth is three at most: compare that to your favorite lisp program)

If you've seen 300+ line react components marching off the right of the screen, you'll know that maintaining the parse tree in your head isn't a barrier to popularity.

300+ line components are not popular

Re: Six years of professional Clojure development

#53

Clojure is the most enjoyable language I've ever used and I love the interactive development. I haven't written code in any other language that even comes close. Unfortunately I am too lazy and careless to use Clojure in any serious capacity though. I really need a Haskell or Rust compiler to remind me of all my silly mistakes. I can't be trusted to get to the same level of confidence through unit tests or linting or…

This looks like something Common Lisp does better, however I have too little Clojure experience to compare. CL (and SBCL in particular) does "good enough" static type checks, it throws warning at compile time (when we compile one function with a keystroke). We can also precise our function types gradually. It isn't a HM type system (Coalton[1] could be it) but it's already great (compared to no compile-time types at all).

Oh, about interactive development: that's sure, CL shines here. Objects get updated (lazily) after a class change, we can install Quicklisp libraries without restarting the image, etc. It's very smooth.

1: https://github.com/stylewarning/coalton

Re: Six years of professional Clojure development

#54
post #22

I loved clojure until working with it for a few years, with some of the famous best teams in Europe and America, including Cognitect people, who ill leave unnamed here. I fell out of love when I realised what the language is - a mutable, imperative, blocking IO by default language with lambdas and zero guarantees at compile time. Effects happen at any time, as it is an imperative language. Just like JS with a better…

What is mutable by default in Clojure? Nothing. You need to explicitly declare mutable variables with a special notation. Are you talking about the underlying VM? Yes, the Java API are mutable, not surprise here, it's not Haskell. Imperative? What is imperative by default in Clojure? Nothing. It's one of the least imperative Lisp, favoring functional constructs all over the place unlike Common Lisp or even Scheme. Bl…

> What is mutable by default in Clojure? Nothing.

All data in Clojure inherits from java.lang.Object. I get what you’re saying, but in real life commercial projects, especially when you use libraries and Java classes, the code ends up with a lot of mutable things. You can never know if any function you call does mutate something without keeping all definitions in your head, and with 20+ people on the project, this is a challenge. Programmers of languages less sexy use frameworks to manage state and effects, but not in FP, which clojurians think they do.

> Imperative? What is imperative by default in Clojure? Nothing.

Please note that I’m not praising Common Lisp or Racket either - the same criticisms apply to them, except they ship with type systems. In Clojure IO is usually done by calling a function that does some (blocking) effect and returns something. That is programming in imperative style. In practice effectful functions find their way into programs, and taints everything referring to it. For this reason, clojure programs written by teams tend not to be as FP.

> Blocking IO. Ok. So you want JavaScript?

I for sure prefer to write a backend where no teammates ever introduce blocking calls. I once worked on a webpage which took minutes to render, because of blocking calls on the back end. It was a mess, after having been worked on for years by around 70 coders, including consultants for the biggest names in Clojurespace.

> Zero guarantees at compile time. Almost true.

Except for syntax errors.

These things turned me off: imperative and blocking IO and effects and no square framework to contain it, combined with zero compile time checks. It results in teams making bespoke solutions that other teams in the company (or even consultants from the famous players in the Clojure space) solving their code needs by meeting with the authors and asking for changes, having a ton of testing to make sure it does not fail in rare code paths, and having one guy on every team religiously adding specs in order to not go mad.

Re: Six years of professional Clojure development

#55
post #50

Clojure is the most enjoyable language I've ever used and I love the interactive development. I haven't written code in any other language that even comes close. Unfortunately I am too lazy and careless to use Clojure in any serious capacity though. I really need a Haskell or Rust compiler to remind me of all my silly mistakes. I can't be trusted to get to the same level of confidence through unit tests or linting or…

Is there something for clojure that TypeScript is for JavaScript?

Clojure has an optional type system: https://github.com/clojure/core.typed

(note that Lisp is flexible enough that a type system can be written as a library)

There's also this for run-time checking (i.e., you won't get any help at compile-time, but functions called with bad values will fail in very clear ways): https://github.com/plumatic/schema

Re: Six years of professional Clojure development

#56
post #33
post #22

I loved clojure until working with it for a few years, with some of the famous best teams in Europe and America, including Cognitect people, who ill leave unnamed here. I fell out of love when I realised what the language is - a mutable, imperative, blocking IO by default language with lambdas and zero guarantees at compile time. Effects happen at any time, as it is an imperative language. Just like JS with a better…

I really like Clojure and I'm glad it is around, but I'll prefer something with strong types any day. From the article I see a lot f reasons why: > "Don't break things!" is part of the culture. If you cannot have compile time guarantees on correctness, the discipline to not break things becomes a key feature. On the other hand, if you have strong correctness guarantees, you may more easily incur some breakage (and th…

In real life projects, you end up doing type checking at runtime, meaning you also need a test for the code path

Re: Six years of professional Clojure development

#57
post #29

Earlier quoted context omitted.

It’s just like C or JS but the first paren goes to the left of the function name.

With function calls, yes. What makes it different is that syntactic constructs are also expressed with the same syntax and there is no special syntax, so control flow constructs use a syntax similar to function calls. This is particularly exuberant in Arc where what in many languages would be: if ( ) { } else if ( ) { } else if ( ) { } else { } Would instead be: (if ) Note the complete lack of syntax beyond a keyword…

Pattern matching in rust:

  match x {
       => ,
       => ,
       => ,
      _ => ,
  } 

  let message = match maybe_digit {
      Some(x) if x  process_digit(x),
      Some(x) => process_other(x),
      None => panic!(),
  };
Seems useful. Python's getting match soon too!

https://doc.rust-lang.org/reference/expressions/match-expr.h...

Re: Six years of professional Clojure development

#58
post #55
post #50

Earlier quoted context omitted.

Is there something for clojure that TypeScript is for JavaScript?

Clojure has an optional type system: https://github.com/clojure/core.typed (note that Lisp is flexible enough that a type system can be written as a library) There's also this for run-time checking (i.e., you won't get any help at compile-time, but functions called with bad values will fail in very clear ways): https://github.com/plumatic/schema

Hopeful new lispers beware that core.typed is not so easy to use as TypeScript, and slows things down quite a bit, and you will need to write a lot of type definitions for 3rd party code. Most (all I’ve seen) clojure shops instead rely on runtime type checking with Spec or Schema, both still popular

Re: Six years of professional Clojure development

#59
post #50

Clojure is the most enjoyable language I've ever used and I love the interactive development. I haven't written code in any other language that even comes close. Unfortunately I am too lazy and careless to use Clojure in any serious capacity though. I really need a Haskell or Rust compiler to remind me of all my silly mistakes. I can't be trusted to get to the same level of confidence through unit tests or linting or…

Is there something for clojure that TypeScript is for JavaScript?

There are a few such things.

The most comparison is core.typed, which literally just adds static (gradual) typing to Clojure. That said, I think that's a misleading comparison, and less useful than it is for TypeScript.

If you're willing to relax the definition to "static analyzers that find similar issues to what TypeScript might find", there are a few that require very little input (but are less powerful in finding these types of bugs, more powerful in finding others) like e.g. clj-kondo or spectrum.

One fundamental challenge is that the idea that you should mostly just pass data around, ideally maps, and those maps should be open for extension, is very core to Clojure. You get a lot of benefits from that, but the idea that anyone can add stuff and that's OK also makes it difficult to detect that some accesses are _not_ OK.

Post reply on HN