Hacker News new | ask | show | jobs
by clartaq 2120 days ago
Clojure is a very pleasant language to develop in. I have found it easier to develop a JavaFX-UI program in Clojure than in Java.

If you want to go the route of running a server on the user's machine and serving it through the user's browser, ClojureScript and Reagent/Re-Frame are excellent choices. Re-Frame, https://github.com/Day8/re-frame, in particular has very nice documentation.

Clojure lets you use anything in the Java universe while ClojureScript gives you access to all the JavaScript stuff, including Node.

There is a lot of tutorial information for both languages.

2 comments

Clojure is a fantastic language, as far as dynamically typed languages go. ClojureScript turned me off to both languages however. I routinely encountered scenarios where accidentally passing values of the wrong type to core standard lib functions produced wildly unexpected behavior that would take hours or even days to debug. Reporting these issues almost always resulted in “don’t do that WONTFIX”, and often very hostile responses if I pressed the issue or even offered to contribute a fix. Ultimately I decided I’d be more productive in a language that embraces correctness as a core feature. And ultimately that led me to take the great FP techniques and philosophy I learnt in clojure and apply them as idiomatically as I could in a statically types language. Now most of my work is in TypeScript, and while I miss a lot of what Clojure has to offer, I would never go back
>I routinely encountered scenarios where accidentally passing values of the wrong type to core standard lib functions produced wildly unexpected behavior that would take hours or even days to debug

Could you provide a concrete example?

Intuitively I do understand ClojureScript is not as seamless as some people say. First of all, Clojure is kind of a database-programming language with fundamental data types built around concurrency, while JavaScript was single-threaded until recently (and web workers used shared-nothing model). Second, Clojure is build around Java specifically, not any other language. Java has some strict type system with immutable complex objects being pretty much native way of doing things, thus Java is great for implementing dynamic types on top of it.

But I feel like not having undeniable proofs of fundamental flaw in ClojureScript. For example, JavaScript fundamentally lacks copy-on-write complex structures. Thus development of copy-on-write libraries is painful e.g. ProseMirror which can become completely broken until page reload which is bad for Single Page Application. However, could it be that ClojureScript... just works?

> Could you provide a concrete example?

I wish I could, it's been years since I've actually written or even read any ClojureScript. But I can offer something more general. Many core functions expecting a collection type would blow up deep in the call stack, usually in helper functions not exposed or documented in the core API, when passed a value which provides no iteration. I would encounter these scenarios frequently when recursing over a nested structure (e.g. oops I passed a keyword or a function to `map`), or when I simply got argument order wrong.

Like I said, this eventually drove me to static typing, and I wouldn't ever consider a language without it again. Most dynamic languages have too large a core interface to commit it to memory, and even "small" languages reproduce that in the libraries we build.

ClojureScript has some oddities compared to Clojure but in my experience acts much nicer than plain JS

Clj-kondo is good to detect unintended passing, in terms of correctness there are sometimes minor fixes but not at the expense of backwards compatibility which is taken very seriously in core

In terms of doing idiomatic Clojure in Typescript, "good" Clojure is data driven Typescript is type driven

Universal data primitives Vs label everything with types aren't terribly compatible

> ClojureScript has some oddities compared to Clojure but in my experience acts much nicer than plain JS

For the most part I agree with this, but... it's not saying much.

> In terms of doing idiomatic Clojure in Typescript, "good" Clojure is data driven Typescript is type driven > > Universal data primitives Vs label everything with types aren't terribly compatible

Huh? What I said is that I try to apply the principles I learnt in Clojure—yes, including writing code that is data-driven, and more importantly value driven—in the most idiomatic way I can within TypeScript. Yes, the whole point of TypeScript is types (it's in the dang name), but:

1. Types describe data. The only major difference between the kind of data described in TypeScript and the kind of data implicitly defined in Clojure is that TypeScript inherited a runtime where mutability is the default and immutability is more a choice of convention than an actual feature of the language.

2. The TypeScript type system is extremely good at describing and statically validating the kind of dynamic polymorphism common in Clojure.

3. Even if it isn't, small and specific interfaces could be used as contracts to achieve roughly the same thing, just with more keyboarding.

Recently I've been working with cljfx for developing a JavaFX app with clojure. cljfx does a great job of creating a re-frame like development experience for JavaFX.