Absolutely, what matters are the programmers first and foremost. We don’t like to say it, but it’s true, the biggest impact a manager can have is to be more selective on who they hire and don’t, and manage to hire a group of better programmers.
The language doesn’t matter much business wise, except in two ways:
- Less talented programmers need to use the lowest common denominator language there is, with the most guard rails, most mature tooling to help them do their job, most amount of online information, tutorial and example, etc. Otherwise they’ll be almost a negative asset, velocity will be very slow, and nothing will get done.
- More talented programmers need to have a reason to work on your product, or they’ll go work elsewhere. So unless your product itself is very interesting and attractive, you’ll need to find a different edge to attract top talent. Can you pay more than others? No? Is your product cutting edge? No? Well are you using an interesting stack? Yes, ok maybe you can still attract some better talent that are interested in that stack. No? Well how do you think you’ll attract talented programmer to your team and retain them?
Unfortunately, there’s a tension between #1 and #2. Also, during Covid, there was a very sudden hiring spree, so even if you had a more interesting stack, you had to compete against someone else, mostly big tech, offering a much much higher compensation, so an interesting stack alone might not have been enough, though that seem to be self-correcting right now.
I guess if you think about it, maybe it would be great if Clojure could be made to fit both #1 and #2, it tends to be very against offering anything for #1, but that also hurts devs who’d like to use it, but work somewhere that isn’t dedicated to always finding top talent with an interest in Clojure, and instead have a mixture of talent, some more talented, some less, and have to make due with that.
FWIW I worked in an organisation where the lead developers were content with the status quo and uninterested in new ideas/concepts/technologies. Until they attended a conference/workshop where the same ideas were presented and they were completely turned around. Maybe that’s a possible strategy, getting an external Clojure developer to hold a presentation/workshop?
(for reference, this was a C++ shop were the arrival of the features in C++17 landed on deaf ears, no matter my efforts to pitch them, until said conference a couple of years later)
Ah, the power of an “outside consultant” to change minds, even when the same proposals have been rejected from existing staff!
While my statement may or may not be dogmatic, I would say Clojure’s design is not. It doesn’t care if you call out to side-effectful Java\JS API. I don’t have to wrap IO operations in an IO monad to maintain purity. It makes a functional approach a default, but it takes into account that real world is unpredictable and has escape hatches to deal with those situations as needed.
Just a minor comment on the side: There are limits to Clojure’s flexibility. See Datatypes and protocols are opinionated at clojure.org. This policy can make Java libraries that build inheritance into their interface a pain to use. It’s not that you can’t do it–I have–but it may be unpleasant (in contrast to most other aspects of Clojure).
I think the fact that they are inheritance-based is what makes them a PITA to work with, regardless of language…
That’s good to know. My instinct would be to just do the inheritance in Java then use Clojure for the initialization. Would that approach have worked if you had to do it again?
That is a great resource on the opinionation of Clojure. It all makes good sense! I guess the cost of those opinions is some interop trouble, yes?
No, that’s not my view about the library I was using. Rather, in order to get the functionality that the library was providing, Clojure forced me to write multiple coordinated definitions in different places. This was partly the result of the way the
gen-class macro works. In the end I wrote a macro to write the different Clojure definitions for me. But the code of the macro is ugly–though it’s as pretty as I could manage–and hiding all of the definitions behind the scenes is not my favorite thing.
You can produce spaghetti code using inheritance. (I learned that by doing it before anyone told me. ) The library mentioned above isn’t like that, imo.
I didn’t write the Java. I used the MASON library for agent-based modeling. At the time, I found no libraries specifically for agent-based modeling written in Clojure, and there were very few actively-maintained ones in Java. MASON was one of the two most popular options, from what I could see, and it seemed better for me than the other one (Eclipse.)
I do think that MASON’s use of inheritance is quite reasonable in the Java world. I don’t think it’s a bad thing, even though I would tend to avoid inheritance if I were writing Java (which I rarely do). There are challenging consequences of MASON’s particular strategy when combined with Clojure. I think that Clojure could support libraries like MASON better. Maybe there’s a danger that people would then start writing inheritance-based Java libraries for use with Clojure–I don’t know–and maybe that would be bad. But then don’t do that! I think Clojure’s “opinionated” policy made it harder for me to use a library which, apart from difficulties of use with Clojure, is a very nice library.
If I was starting from scratch at this point, I would put serious investigation into using the Clojure library spork, whose capabilities overlap with MASON’s, though it possibly isn’t ideal for my use cases. When I started using MASON, either I was unaware of spork, or it didn’t look promising for my uses, but I would give it a look again at this point. (I have a lot of respect for the author, @joinr , who’s been very helpful in various contexts.)
From the scicloj website, I see that dsim might be another option. At one time I didn’t realize how much overlap there was between what’s covered by the terms “discrete event simulation” and “agent-based modeling”, although there are different central use cases associated with the two terms.
There have been a lot of great thoughts here, particularly concerning the unique benefits of Clojure as a language and about the ecosystem. I wonder if this can be brought back to the original, more basic question of just being hosted? What are the trade-offs of being hosted vs being original from the bottom up?
‘Hosted language’ to me is about running on an existing platform, for instance an interpreter or virtual machine. It’s susceptible to the same kind of ‘word inflation’ that has occurred with the low-level/high-level distinction in programming languages, where C used to be called a high-level language and is now almost universally considered the penultimate extreme in low-level programming after assembly! Even entirely new programming languages such as Rust are implemented for LLVM, yet I don’t think anyone would call Rust a hosted language.
In my opinion, the reason why being a hosted language for the JVM is such a good thing for Clojure is that none of Clojure’s unique features are relevant to how it’s implemented. Clojure has brought Lisp syntax and modern, immutable data structures into non-academic programming like no other language has, but doesn’t claim to improve upon aspects like the design of OS interfaces like does Haskell or improved memory management as with Rust. Instead, building upon the JVM as an abstraction means that Clojure passively benefits from the ongoing improvement of Java, allowing it to actively pursue other goals.
Excellent points! I like what you said about inheriting passive benefits.
This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.