Live data from Hacker News

Why Clojure?

gaiwan.co

251–260 of 302 posts

Re: Why Clojure?

#251

Earlier quoted context omitted.

Coming from a love of strong typing (scala) clojure dynamic typing was a real adjustment. One thing I grew to really love is how small my changes were when I’m just adjusting a decidedly brownfield chain of functions that operate on data. With go in place at work, I added a couple fields to a core data type in my business and I ended up with thousands of lines of changes to pipe them everywhere. Doing the correspondi…

The Haskell type `[x] -> [x]` (the equivalent of `List[A] -> List[A]`) tells you an incredible amount about the function. It tells you that the function must calculate a subset of a permutation of the input list. The function cannot be anything else (or else it will crash or hang). In a language with stricter requirements you can omit even the crash/hang caveat. Don't underestimate the amount of information even simp…

Yeah, Hickey was just wrong about this. For me, watching his talks goes like this:

Hickey: I value X, Y, Z

Me: Yeah man!

Hickey: We get great consequences A, B, C

Me: Ah yeah, I love programming like that. That's why I love Haskell!

Hickey: That's why Haskell is bad.

Me: err, what!?

> It tells you that the function must calculate a subset of a permutation of the input list

As tromp pointed out, "permutation" is technically incorrect. You mean something like "a list formed only from elements of the elements of the input list, and the particular arrangement is independent of the values of the input list"!

Not sure why you were downvoted though.

Re: Why Clojure?

#252

Earlier quoted context omitted.

If you like the language, don't let that stop you. Install leiningen and run: `lein new app my-stuff`. Then type `lein repl` and you should have a repl running. Alternatively, open the project in IntelliJ with Cursive installed or VSCode with Clava or other supported editors and start evaluating code at the repl. Go through a few tutorials, then go through one of the free books available online. Don't give up when yo…

Well, also, sadly, the first thing I would want to be right now happens to be... a GUI, which seems to be the archnmesis of Java in general, and clojure in particular ;)

If your target is the web browser, then Clojurescript is your friend. There's Clojure Dart for mobile, cljsrn for React Native, Clojure CLR for .Net

Re: Why Clojure?

#253
post #184

Earlier quoted context omitted.

But have you seen flow ? I don't think it's stalled at all, and Nubank seems to have become an enabler to the ecosystem. I mean, Datomic is free to use! [core.async.flow]: https://github.com/clojure/core.async/commit/03b97e0b3e0ec32...

I really don't understand what flow is and what problem it solves. I've read the commit comments and some posts but I still don't get it.

Here's Rich Hickey's explanation if it helps: https://www.reddit.com/r/Clojure/comments/1i27n1k/rich_intro...

His comment walks you through what it's for. The basics: configure your flow of data from producer to queue to consumer and so on as data, in one place.

Re: Why Clojure?

#254

Earlier quoted context omitted.

No, defprotocol and deftype have the same properties as Java interface and Java classes, and the types are checked at compile time. This is static typing. Period. Clojure is a compiled language, it does check typing during compilation.

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 libraries rely on dispatch on type to work, so they are taking advantage of the type checking.

Of course, you will say, "oh, clojure is not normally AOT, so it's not dong the checks.", but that's another issue. The issue at hand is this: can you write Clojure such that types are checked at compile time. The answer is YES.

The compiler may run only when you run the program, that's a different issue. You are confusing these two issues.

If you want a separate compile stage, then basically you are already excluding runtime compilation, i.e. you are arguing against runtime compilation. So it's not really about typing, but about how you want to run the program. Isn't it? You want AOT for everything, you don't want runtime compilation. That's it. It has nothing to do with types.

Re: Why Clojure?

#255
post #93

I've been working in Clojure now for about 12 years. Maybe 12+ years of Java prior to that. I've created some great apps, and great libraries (in both Clojure and Java). I often describe Clojure as "the least worst programming language", which is an off-handed complement, but I think accurate. Things you don't like can generally be fixed (at least locally) using macros and libraries. The core is strong, a good basis…

How does the REPL approach scale in very large codebases? I.e. code that talks to multiple services, complex configurations, etc..

https://polylith.gitbook.io/polylith

Re: Why Clojure?

#256

Earlier quoted context omitted.

Then you are not writing in defprotocol everywhere style. The keyword is everywhere. All the domain objects are deftype or defrecord. Try that. It is the same as Java, basically. It is not an anti pattern, it is the way most low level libraries and clojure itself are written. Clojure is a tool, not a cult. This core team worship is turning people away. The core team made plenty of mistakes, and got called out, rightf…

Even if you did, that wouldn't solve the problem because many checks are still done at runtime. Also, if you started doing that then you might as well just write Java at that point. I've worked on code bases structured in this way and it's absolutely terrible to work with. For one, protocols completely break any sort of REPL driven development. Most libraries are absolutely not written in this way either. Please poin…

That has nothing to do with types. You are now talking about when a compiler is run.

Clojure gives you the option to run the compiler at runtime, so that's what people normally do. However, you can also run the compiler at compile time. Right?

For people who want type checking, they can opt to write Clojure in this defprotocol everywhere style, and turn on AOT. Then they basically get the same thing as what Java gives them.

As to example of libraries that are defprotocols everywhere, you should look at any of the low level performance minded libraries in the Clojure ecosystem, they are either written in this defprotocols everywhere style, such as nippy, neanderthal, dtype-next, and so on, or mostly in Java, such as http-kit, fast-edn, etc. I noticed this phenomenon, because my own libraries, editscript and datalevin, are written in this way. I take comfort that my fellow performance minded library authors are doing the same. Finally, isn't Clojurescript entirely driven by protocols?

So really, there are two kind of Clojure programmers. One type writes application code or high level libraries, and they write normal Clojure code all the time. However, there are also those who write primarily low level library code, which are used by the first camp, and their code is full of defprotocol and deftypes. So defprotocol everywhere is not anti-pattern. It's anti-pattern only in the mind of the first camp of programmers, and that's a narrow minded way of looking at things. Even the first version of Clojure Programming book by the core team members, are written in a way that's full of defrecord. Remember?

This "everything is a map" orthodoxy is turning people away from Clojure. Just let people write the code that suits their own needs. We can use more people who are pragmatic instead of dogmatic in the Clojure world. If you trust Rich Hickey's judgment, then you should trust him put in the features Clojure has for good reasons. Macros and protocols are part of the Clojure language, and you should be using them when the use case calls for them. Stop the "anti-pattern" nonsense.

Re: Why Clojure?

#257
post #185

Earlier quoted context omitted.

You can keep a JVM running in the background with your project loaded and send stuff there from your IDE/editor. I don't think this is possible with JavaScript.

So they try to make the least-worst JVM environment which is great if you're dead-set on using the JVM, which has a lot of pros. For most people Python/Javascript also does the job and you don't need to learn another paradigm — a Lisp — to code for it, which also makes sense. However, learning a Lisp also makes you a better coder because of immutability and less side-effects. Hence why Clojure is still around.

> learning a Lisp also makes you a better coder

It can do, but it also can make you a worse coder. Specifically in typed languages.

One of the issues I've ran into with Clojure devs doing Java is that instead of relying on a type, they tend to want to write stuff like `Map>`. Even when the key sets in both maps are well known.

This becomes worse when you mix that with Immutability. Immutability can be fine except when you need a mutation. In applications that require heavy mutation of data a `Map>` is one of the worst ways to represent structured data, copying that structure is EXTREMELY expensive.

This isn't to say that you shouldn't usually strongly prefer Immutability. But it's also to say you shouldn't underestimate the cost of allocations and copying data.

Theres always tradeoffs. Part of being a good programmer is knowing when those tradeoffs are best applied.

Re: Why Clojure?

#258

Earlier quoted context omitted.

Through the last decade, I have found that programmers' judgment of technologies, tools, and languages are incredibly noisy. It is hard to make correct decisions based on opinions alone, and design by committee is a real thing. Common Lisp was the most mind-blowing language I ever touched, and it seems the creator of Clojure really filled the gap between the brilliant simplicity of Lisp as a language and the access t…

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 concurrency models also available on Common Lisp, including async, channel-based, etc.

> Only lists are actually functional, concurrency is YOLO-tier, etc.

I'm sad you had that experience, but there is tons of solid concurrency support in Lisp, for example lparallel is awesome.

Clojure is nice as a JVM language alternative, that is, better than Kotlin, Groovy, etc.

However the loss of the great interactive development facilities that Common Lisp has is a major, major downside. Interactive development is what makes CL (and also Smalltalk/Pharo) great.

Re: Why Clojure?

#259
post #93

I've been working in Clojure now for about 12 years. Maybe 12+ years of Java prior to that. I've created some great apps, and great libraries (in both Clojure and Java). I often describe Clojure as "the least worst programming language", which is an off-handed complement, but I think accurate. Things you don't like can generally be fixed (at least locally) using macros and libraries. The core is strong, a good basis…

I gave Clojure a shot some years ago and even wrote an important tool used daily by all employees at our company in Clojure. The problem for me was maintenance. If I had to make any change to that code, I had to dive into the REPL just to understand it. Whereas with something like Java, even if something is poorly written and not documented, I can get at least a minimum understanding of the code just looking at the t…

What about core.typed. I find gradual type systems to be hard to work with for some reason.

Re: Why Clojure?

#260

I love writing Clojure. Whenever I say that publicly, there are inevitably some voices challenging my stance with skepticism, criticism, and attempts to discredit whatever I say provides practical value for me. Then I have to explain to them, "no, it's not the only language I know," "yes, I've used dozens of other languages before," "yes, including languages with robust static type systems as well." And you know what…

Did you or any of your fellow devs have ADD or ADHD? How did they adapt to dynamic types? I have ADD and I once heard that devs with ADD/ADHD have an incredibly small heap size for context but compensate for their weakness by being great at solving logical problems in that small heap. Types have been essential for me when functioning in code bases. I really struggle with pure JS and untyped Python. Clojure was simila…

>How did they adapt to dynamic types?

You mean dynamic typing, I understand.

Clojure (and Common Lisp) is strongly typed, so if you expect type A and you give a value of type B, an error will be raised.

On Common Lisp, which is an interactive development language, you just inspect the stack frame where the error was raised, find the problem, correct the code, recompile your function (while the code is running), and "restart" the stack frame, so the execution continues (without having to restart or redeploy everything and try to replicate the bug). Thus, it is no big deal at all.

On Clojure i'm not so sure how extensive is the interactive support. But there is "spec", which can help.

Post reply on HN