Live data from Hacker News

Why Clojure?

gaiwan.co

261–270 of 302 posts

Re: Why Clojure?

#261
post #164

Earlier quoted context omitted.

I've never seen anything but praise for clojure.

The dynamic typing and "everything is a map" can be a PITA. At the moment I'm working on a codebase that has I/O to JSON APIs, Avro schemas and postgres databases. That means that a field called "date" can be either a string, integer days since the epoch or a Java Date, and (because this codebase isn't great) there's no way of knowing without tracing the call stack. With the right discipline (specs, obsessively norma…

>That means that a field called "date" can be either a string, integer days since the epoch or a Java Date, and (because this codebase isn't great) there's no way of knowing without tracing the call stack.

But this is because JSON is an untyped data structure. (And btw, a flawed one...)

You would have this problem in any programming language.

Re: Why Clojure?

#262
post #162

Earlier quoted context omitted.

I use Integrant to make systems out of components that are tied together at runtime. I have the option of running real versions or mock versions in tests or the REPL, with config drawn from the environment or config files or parameters. I can boot or reboot any combination of components at will. It’s fairly easy to divide and conquer this way.

I like integrant, but I feel like a lot of the examples I see use it for each web endpoint, which seems like a massive amount of overkill to me. I tend to use it just for the router, but it sometimes feels like I'm not using the library to its full potential with that.

Do you have an example? On the face of it I agree that seems like a baffling thing to do.

Re: Why Clojure?

#263

The part about the "stability" is a bit surprising - in my experience, I try playing with clojure about once a year, and every time, everything is different (I mean, I had to go through classpathes, then lein, then boot, then deps.edn - what is the current way to "try and run a program" du jour ?) Also, is running your "hello world" still going to be incredibly slow, or has something changed in the core system (I kno…

10+ years ago Clojure had a fantastic introductory experience. lein new and away you go. lein was so good and effective, for both tiny hello world projects and real production apps. The experience has gotten worse and worse now for a decade. The core team have continued to take things in a worse direction (supported by a small group of fanboys) and most newcomers are now completely baffled by the tooling.

Also, today, half the docs you find around are about lein, half are about tools.deps, and no one ever gets the full definition because they assume you know your way around. :shrug:, I guess ?

Re: Why Clojure?

#264
The two things I ever enjoyed that is some kind of programming was building a pipeline in shell to process data and for the last almost 5 years writing Clojure and ClojureScript. We are now 4 guys writing Clojure with 30+ years of Clojure experience added together. I participated as a co-founder in a front-end heavy project in Clojure/ ClojureScript and more than a year ago started a Clojure-preferring consultancy in Prague, Czechia. For stuff like Inter-dealer broker trading system it's a no-brainer. For many other things as well. Even for distributed systems/ higher level infrastructure stuff it might be a good choice to get going at least.

Re: Why Clojure?

#265
post #192
post #174

Earlier quoted context omitted.

I'd emphasize that it's a problem with your particular code base. If you set it up correctly, all dates are properly parsed at the boundaries and you would only deal with one type of date inside your app. I'm working on a large Clojure app with a lot of date handling and never had any issues. For me, a date is always juxt/tick date.

The parent comment illustrates the problem with one clear example. In real-world code functions pass around amorphous maps, they add, subtract and transform fields. There is no way to know what's being passed around without reading the source of the whole chain. Statically typed languages reduce the need to know how the data is structured or manipulated. The market has clearly chosen this benefit over what Clojure ca…

Yes and no. Statically typed languages only know that data stored in some piece of memory was conforming to some kind of shape/ interface when it was first stored there. That's why tricks like SIMD Within A Register (SWAR) work at all. E.g. when you need to parse temperatures from string input very fast like in the 1BRC: https://questdb.com/blog/billion-row-challenge-step-by-step/ How does your type system help there?

With static typing, you are doing specification and optimization at the same time, which is maybe necessary because compilers and languages are not sufficiently smart but also because of this mix it complicates reasoning about correctness and performance. Also static typing introduces a whole universe of problems with itself. That's why we have reflection or stuff like memory inefficient IP address objects in Java:

For a simple IPv4 address normally representable using 4 bytes/ 32 bits Java uses 56 bytes. The reason for it is Inet4Address object takes 24 B and the InetAddressHolder object takes another 32 B. The InetAddressHolder can contain not only the address but also the address family and original hostname that was possibly resolved to the address.

For an IPv6 address normally representable using 16 bytes/ 128 bits Java uses 120 bytes. An Inet6Address contains the InetAddressHolder inherited from InetAddress and adds an Inet6AddressHolder that has additional information such as the scope of the address and a byte array containing the actual address. This is an interesting approach especially when compared to the implementation of UUID, which uses two longs for storing the 128 bits of data.

Java's approach is causing 15x overhead for IPv4 and 7.5x overhead for IPv6 which seems excessive. Is this just bad design or excessive faith in static typing combined with OOP?

Re: Why Clojure?

#266
I love Clojure. I has influenced me more than any other language. It is without question the single most coherently designed programming language I know. I've written a fair amount of it, contributed to libraries, some of them core, so I hope folks don't interpret this as drive-by criticism.

The biggest problem I had (and still have) with Clojure is that, even in its heyday (circa 2014-2018 or so) I couldn't convince people to keep using it. It seemed like every smart, senior engineer I knew tried it, loved it, wrote load-bearing stuff in it, and then walked away: either abandoned it at their companies, abandoned it for personal projects, or started companies using other languages instead of Clojure. And this was when Clojure was hot shit. Big Data was all the rage, and everyone had heard of or was using Storm. Clojure was the language.

You might counter that maybe me or the people I know are fools, not smart enough for Clojure, or picked stupid languages for the wrong reasons, or followed the crowd, or whatever else. And you might be right!

But all I know is that the smartest people I know tried Clojure, learned it, respected it, learned a ton from Rich about how to think about systems, and ultimately walked away, because they were, variously, repelled by what they perceived as:

  - the elitism in the community
  - the elitism in the core team
  - the impenetrability of the tooling and the unwillingness of anyone to admit that it sucked
  - the sometimes not so subtle denigration of their skills as professionals for having the audacity to, for example, use web frameworks rather than build everything from scratch
I bring this up because for me programming is social. I love being able to write code that does something fun and/or useful and tickles that part of my brain that loves expressing what I want in a beautiful way, but ultimately it's more useful to be to be able to write code that my friends and colleagues can understand and are willing to use.

So I have to wonder, is it sustainable for a community to be as reliant on true believers as Clojure seems to be? Is it sustainable to alienate as many of those folks who maybe aren't true believers, but who would love using it anyway? Who knows, maybe it is! But I can tell you: I'm Clojure's audience, and I don't use Clojure today, and none of my now-Staff and Principal and CTO level friends are using it or teaching it to the juniors on their teams or choosing it for their companies. Why? Wouldn't it be better if we were?

Re: Why Clojure?

#267

Earlier quoted context omitted.

If you already like Common Lisp, what Clojure brings are: 1) runs on the JVM, access to any Java or Python library within Clojure without wrappers 2) an immutable-by-default language with a standard library that takes advantage of it 3) the best out-of-the-box concurrency story of any language I know of 4) a very well-developed ecosystem for developer tooling and general project stuff Common Lisp is very fun, but the…

> runs on the JVM, access to any Java or Python library within Clojure without wrappers If you already like Common Lisp, ABCL (Armed Bear Common Lisp) is a mature fully ANSI Common Lisp-compliant implementation, that runs on the JVM and can instance or load Java classes or call Java methods without wrappers and in only one line of code. > the best out-of-the-box concurrency story of any language I know of Lots of con…

I consider mutable concurrency models to be YOLO-tier.

I disagree Common Lisp has a better development environment, I haven't found that to be true.

But use whatever makes you happy!

Re: Why Clojure?

#268

Earlier quoted context omitted.

Protocols do not work like Java interfaces or classes. Their methods are compiled into regular functions which lookup the implementation to use at runtime based on the runtime type of the receiver. Compilation will check for the named function but doesn't do any further checking. Given the following protocol and implementation: (defprotocol P (method [this ^Integer i])) (extend-protocol P String (method [s i] (.subst…

deftype IS a Java class, it's not compiled into something else. What is a Clojure function? A Clojure function is a Java class. Clojure is a compiled language, so it does check types, just like Java check types. So if you use defprotocol and deftype for every domain objects in your code, your code won't compile if there's a type error. Try it. BTW, that's the way many Clojure libraries are implemented. These librarie…

Of course Clojure has to ultimately be compiled into a native format for the host platform, bytecode in the case of the JVM implementation, but that doesn't require type checking in the same way Java does.

Clojure functions are compiled into implementations of clojure.lang.IFn - you can see from https://clojure.github.io/clojure/javadoc/clojure/lang/IFn.h... that this interface simply has a number of overloads of an invoke method taking variable numbers of Object parameters. Since all values can be converted to Object, either directly for reference types or via a boxing conversion, no type checking is required to dispatch a call. With a form like

  (some-fn 1, "abc", (Object.))
the some-fn symbol is resolved in the current context (to a Var for functions defined with defn), the result is cast (not checked!) to an instance of IFn and the call to the method with required arity is bound. This can go wrong in multiple ways: the some-fn symbol cannot be resolved, the bound object doesn't implement IFn, the bound IFn doesn't support the number of supplied arguments, the arguments are not of the expected type. Clojure doesn't check any of these, whereas the corresponding Java code would.

Protocol methods just get compiled into an implementation of IFn which searches for the implementation to dispatch to based on the runtime type of the first argument, so it doesn't introduce static type checking in any way.

Re: Why Clojure?

#269
post #60

The part about the "stability" is a bit surprising - in my experience, I try playing with clojure about once a year, and every time, everything is different (I mean, I had to go through classpathes, then lein, then boot, then deps.edn - what is the current way to "try and run a program" du jour ?) Also, is running your "hello world" still going to be incredibly slow, or has something changed in the core system (I kno…

I have been building my (money-earning SaaS) app with leiningen for 10 years now. There is no "du jour", unless you choose to be "du jour". If you care about startup time (I don't, my app starts only once), you can use babashka for scripting.

I don't disagree with you from the perspective of someone who is already in the community and already has the experience to make that choice, but I think this question is slightly more complicated for someone with zero Clojure experience. More than once I have seen people confused on whether they should be using Lein, Boot, the first-party CLI, Maven, Shadow CLJS, Figwheel, or something else entirely.

Re: Why Clojure?

#270

Earlier quoted context omitted.

> I know people talk about python being Lisp without brackets What on earth?? Who are these people, this is the first I've heard of this and am having trouble understanding what the argument could be. Like, basically all languages get transformed to an AST as part of the compile step soooo I guess any language is sort of a lisp.

Peter Norvig: https://www.norvig.com/python-lisp.html - "Basically, Python can be seen as a dialect of Lisp with "traditional" syntax (what Lisp people call "infix" or "m-lisp" syntax). One message on comp.lang.python said "I never understood why LISP was a good idea until I started playing with python." Python supports all of Lisp's essential features except macros, and you don't miss macros all that much because it…

Ha, fair enough. Thanks!
Post reply on HN