Live data from Hacker News

Six Years of Professional Clojure

engineering.nanit.com

191–200 of 254 posts

Re: Six Years of Professional Clojure

#191
post #19

> ... and the question regarding choosing Clojure as our main programming language rose over and over again If I find myself having to repeat myself justifying a certain decision time and time again, it's an indicator that the decision needs to be revised to be something which is a more intuitive fit for the organization.

I donno why you're being downvoted, it's a questionable decision and probably the company would have been better off with Python/PHP/Node. Hiring and onboarding are extremely important for a startup. You know what else? Finding answers to common questions on Google/Stackoverflow; I am now working with Ember and can tell you guys you take a 50% productivity hit by using a tool that's obscure on Google. Sure once you b…

> I donno why you're being downvoted

Oh that's easy - the voting system is a way to know how conformant you are to other opinions coffee smile

Re: Six Years of Professional Clojure

#192

Earlier quoted context omitted.

This is one of those self-inflicted Clojure problems. In Common Lisp you might use an alist or a plist for small things, but you'd definitely reach for CLOS classes for things that had relationships to other things and things that had greater complexity. IIRC, the preference for complecting things via maps, and then beating back the hordes of problems with that via clojure.spec.alpha (alpha2?) is a Hickey preference.…

No source to back this up, but my guess is that Clojure was driven by the need to interopt with Java so is to not get kicked out of production. This meant absorbing the Java object model. Shipping a language with both Java objects and CLOS and making them both play nice together sounds like a nightmare.

There's a Common Lisp implementation on the JVM, called ABCL: https://www.abcl.org/ The interop is... not the best, but it's something. I've only used it for proof-of-concept stuff (e.g. how-to make a Lisp module, export it as a jar that java code can include in their pom and use without knowing it's Lisp) and for minor development experience enhancements in a giant Java codebase (e.g. change method in Java, it gets hot-swapped in, I invoke it or an upstream method from Lisp with real data so I don't have to make an even higher upstream network request via some deep UI section).

Re: Six Years of Professional Clojure

#193
post #3

I found one of the perceived weaknesses of Clojure (in this article), it being dynamically typed, is a tradeoff rather than a pure negative. But it applies that tradeoff differently than dynamic languages I know otherwise and that difference is qualitative: It enables a truly interactive way of development that keeps your mind in the code, while it is running. This is why people get addicted to Lisp, Smalltalk and si…

> These can be gained back with clojure spec and other fantastic libraries like schema and malli. What you get here goes way beyond what a strict, static type systems gets you

That reads like what someone would think when they used the typesystem of Java 6 and now think that this is what "statically typed programming" means.

No, you can _not_ get back what types give you by any kind of spec - if anything you can get some of the benefits of types, but you also pay a price.

The thing is - dynamically typed languages don't really seem to evolve anymore. They add a bit of syntatic sugar here and there and sometimes add some cool feature, but mostly only features that already existed for a long time in other languages. At least that is what I have seen over the past couple of years, I would be happy to be proven wrong.

Looking at statical typesystems however, there is much more progress, simply because they are much more complex and not as optimized. From row-types over implicits and context-expressions towards fully fledged value-dependent typesystems, which have amazing features that start to slowly trickle down into mainstream languages like Typescript or Scala.

While both dynamically and statically typed languages have their pros and cons and it will stay like that forever, I expect that statically typed languages will proceed to become the bigger and bigger piece of the cake, simply because they have more potential for optimizations going forward.

Re: Six Years of Professional Clojure

#194
post #3

I found one of the perceived weaknesses of Clojure (in this article), it being dynamically typed, is a tradeoff rather than a pure negative. But it applies that tradeoff differently than dynamic languages I know otherwise and that difference is qualitative: It enables a truly interactive way of development that keeps your mind in the code, while it is running. This is why people get addicted to Lisp, Smalltalk and si…

In 2021, I find it hard to justify using a dynamically typed language for any project that exceeds a few hundreds of lines. It's not a trade off, it's a net loss. The current crop of statically typed languages (from the oldest ones, e.g. C#, to the more recent ones, e.g. Kotlin and Rust) is basically doing everything that dynamically typed languages used to have a monopoly on, but on top of that, they offer performan…

We can debate this forever, but all I can say is that at my work we have equal part Java and Clojure, and we have some Kotlin and sole Scala as well. Out of all of them, Clojure does not cause us anymore issues, it doesn't take us any longer to add features, it doesn't perform any worse, and it doesn't have any more defects than the others.

My conclusion is that it's a matter of personal preference honestly. Those are all really good languages. Personally I have more fun and enjoy using Clojure more. I would say I tend to find I'm more productive in it, but I believe that's more a result of me finding using it more enjoyable then anything else.

Re: Six Years of Professional Clojure

#195
post #29
post #22

Earlier quoted context omitted.

I've admittedly not played with spec, but can't you solve documenting interfaces by defining `defrecord`s ? You rarely really care about the actual types involved. You just want to know which fields you either need to provide or will recieve

Spec will give you stronger feedback than a docstring or function signature. It can tell you (in code terms, with a testable predicate) if a call to an interface wouldn't make sense. Eg, spec can warn you when an argument doesn't make sense relative to the value of a second argument. Eg, with something like (modify-inventory {:shoes 2} :shoes -3) spec could pick up that you are about to subtract 3 from 2 and have neg…

> Eg, spec can warn you when an argument doesn't make sense relative to the value of a second argument.

That's something that dependently-typed typesystems easily do as well if not better because inside of the function or data definition, the information is still available and used for code-completion, other compiletime checks etc.

Re: Six Years of Professional Clojure

#196
post #181

Earlier quoted context omitted.

> automatic refactorings (pretty much impossible to achieve on dynamically typed languages without human supervision) ...are we talking about the thing pioneered by Smalltalk's Refactoring Browser?

My question is how does that work in a dynamically typed language? In static typed language we can know scope & type of a variable and we can't change much in runtime.

In Clojure you know the number of arguments to a function and the name of functions and variables, and the code is all very well structured as an AST (being a Lisp).

So you can do a lot of refactorings with that such as:

Rename function, rename variable, rename namespace, extract constant, extract function, extract local variable, extract global variable, convert to thread-first, convert to thread-last, auto-import, clean imports, find all use, inline function, move function/variable to a different namespace, and some more.

The only thing is you can't change the "type" of something and statically know what broke.

Re: Six Years of Professional Clojure

#197

Earlier quoted context omitted.

Not who you are responding to, but the common idea that static types are all win and no cost has become very popular these days, but isn't true, it's just that the benefits of static typing are immediately apparent and obvious, but their costs are more diffuse and less obvious. I thought this was a pretty good write up on the subject that gets at a few of the benefits https://lispcast.com/clojure-and-types/ Just to n…

Your third point about having to encode everything isn’t quite true. Your example is just brittle in that it doesn’t allow additional values to show up causing it to break when they do. That’s not a feature of static type systems but how you wrote the code. This blog post[1] has a good explanation about it, if you can forgive the occasional snarkyness that the author employs. In a dynamic system you’re still encoding…

It's important to note that this article talks about something that is missing from most statically typed languages.

It's best to refrain from debating static VS dynamic as generic stereotype and catch all.

You need to look at Clojure vs X, where if X is Haskell, Java, Kotlin and C#, what the article talks about doesn't apply and Clojure has the edge. If it's OCaml or F# than they in some scenarios don't suffer from that issue like the others and equal Clojure. But then there are other aspects to consider if your were to do a full comparison.

In that way, one needs to understand the full scope of Clojure's trade offs as a whole. It was not made "dynamic" for fun.

Overall, most programming languages are quite well balanced with regards to each other and their trade-offs. What matters more is which one fits your playing style best.

Re: Six Years of Professional Clojure

#198
post #3

I found one of the perceived weaknesses of Clojure (in this article), it being dynamically typed, is a tradeoff rather than a pure negative. But it applies that tradeoff differently than dynamic languages I know otherwise and that difference is qualitative: It enables a truly interactive way of development that keeps your mind in the code, while it is running. This is why people get addicted to Lisp, Smalltalk and si…

In 2021, I find it hard to justify using a dynamically typed language for any project that exceeds a few hundreds of lines. It's not a trade off, it's a net loss. The current crop of statically typed languages (from the oldest ones, e.g. C#, to the more recent ones, e.g. Kotlin and Rust) is basically doing everything that dynamically typed languages used to have a monopoly on, but on top of that, they offer performan…

Not only this, but the programming style where you pass around dictionaries / maps for everything yet have expectations about what keys they contain works just as easily in JS, and with TypeScript or Flow you get a lot more help from the compiler than you do using spec (as I understand it).

Re: Six Years of Professional Clojure

#199
post #119

Earlier quoted context omitted.

How did you make the switch? Were you already working for the same company? Did you already know Clojure, from open source, or side projects?

I work at Ladder [0], and almost everything is done in Clojure/ClojureScript here. I had no previous experience in Clojure – Ladder ramps you if you haven't used it before. My interview was in Python. We're currently hiring senior engineers, no Clojure experience necessary [1]. [0] https://www.ladderlife.com/ [1] https://boards.greenhouse.io/ladder33/jobs/2436386

Remote from everywhere or only in USA?

Re: Six Years of Professional Clojure

#200

Earlier quoted context omitted.

My question is how does that work in a dynamically typed language? In static typed language we can know scope & type of a variable and we can't change much in runtime.

In Clojure you know the number of arguments to a function and the name of functions and variables, and the code is all very well structured as an AST (being a Lisp). So you can do a lot of refactorings with that such as: Rename function, rename variable, rename namespace, extract constant, extract function, extract local variable, extract global variable, convert to thread-first, convert to thread-last, auto-import,…

All these refactorings can only be done automatically and safely if you have type annotations (i.e. core).

Without them, all these refactorings can break your code (as in, not even compiling, let alone run).

Post reply on HN