Blog for the Klipse project, covering Clojure, JavaScript, data-oriented programming, compilers and interactive code snippets in blog posts.
HN links it for its data-oriented programming principles and the Klipse plugin for interactive code snippets, with commenters suggesting it be used for more articles.
> I can't get past the lack of currying.
Say again? Currying may not exist as a special form, but adding it is utterly trivial: [0]
Which I guess is where Lisp shines. Modifying the language to suit your needs is easy. You aren't bound by the limits that many languages force upon you.
That being said, I wouldn't say that Common Lisp or Ocaml have the same userbase. In much the same way that C and JavaScript don't serve the same domain.
ML languages are about safety, and correctness.
Lisps tend more to be about speed of development, and flexibility.
That being said, as just about any paradigm can be implemented in a modern Lisp, and perhaps older ones as well, there are places where they can cross over with this want of correctness.
Racket is an experimental Lisp that grew out of Scheme, and is basically a family of languages, or a Lisp-ish language framework for creating other languages. Among the inbuilt languages, is typed/racket [1]. It uses contracts or inference to ensure type safety at compile time. Due to Racket's language features, if you add contracts, typed/racket can use, or be made use of, by other Racket languages, like lazy/racket[2] and scribble[3].
Other Lisps can have similar things, as you saw with currying, Common Lisp can have compiler hints, or even static typing [4]. Clojure has a ML style matching library [5], inbuilt.
Basically, where you might hit a "I'm approaching this problem the wrong way" in most languages, you can simply write a quick,…
I understand your worry, but I've had a quite opposite take on this.
I think we can agree that it's not that hard to find ANY job as an experienced developer. However it's much more difficult to find a great, satisfying job. For that you need to navigate around a lot of corpo-bullshit type of projects, and Clojure has served me well as a useful filter in doing that.
My reasoning is that Clojure is niche enough that when company is using it, you can assume that it's due to a deliberate technical choice, and not just because of its popularity. That tells me two things that are symptomatic, in my opinion, of a healthy tech company culture:
- tech decisions are made by engineers, not by top-level executives,
- their conclusions and bets align with mine because we all see and agree on Clojure's edge over more popular solutions.
Admittedly, there's always a risk that someone just followed the hype and got out of their depth but I think this risk is relatively small, because Clojure's no longer a new kid on a block and choosing a tech stack is a major decision and usually done by senior tech leadership, hopefully less hype driven.
Of course, Clojure is no silver bullet and it's just a tool that gives you enough rope to hang yourself. Messy codebases are just as possible as in other languages, especially when the team is new to lisps that are very different from mainstream languages, but that's a nature of software development - you learn with the experience. I do cringe when I…
As a Clojure programmer, this is not what I have in mind when I think of data-oriented-programming, but this:
Principle #1: Separating code (behavior) from data.
Principle #2: Representing data with generic data structures.
Principle #3: Treating data as immutable.
Principle #4: Separating data schema from data representation.
Source: https://blog.klipse.tech/dop/2022/06/22/principles-of-dop.html
I think using C++ gives a different twist to the meaning of data-oriented, mainly because with lisps code is data. As I read this "manifesto", it seems more focused on the data the program handles than handling the program with data: In Clojure I often use data-oriented programming for programs that barely deal with any data at all. I tend to lay what I call a "plan" that describes the computation that needs to be carried out. In some way this is similar to a DSL except that this "plan" won't run without also writing a "compiler" or "interpreter". If suddenly requirements change and you need to run your "plan" in a distributed way (or any other execution flavor you may think of), you just write another compiler.
Code being data, this is an approach you can take on code itself with macros, not just as a way to add behavior but to split different aspects of code: I once wrote a macro specifically for a block of complex code that I wanted to read without the clutter introduced by debug lines, so I moved this code in a macro that would add it back using a highly specific…
Your small dive prompted me to create a simple version of what you were describing [1]. I didn't use my usual editor, and just used the cljsfiddle itself.
I really wanted to create a spec for the data in app-state, and check the value in the app-state atom each time I edited it (perhaps with an add-watch). That gets you many of the same advantages of static typing, but you only add the extra insurance when you think its worthwhile instead of always.
Instead of using strings for time-choices and page-choices (in the code at [1]), you can use maps like
[{:title "Day" :time 24}, {:title "Hour" :time 1}...]
and expand when nessicary. It shouldn't be too difficult to keep them in sync this way.
You might want to check out clojurescript again sometime soon. Clojure.spec (and cljs.spec) are going to offer a huge jump in usability. Clojure.spec is a tool kit, and specs are basically definitions of data, that can be used for parsing, unparsing, and generating that very data. The beginning of this (interactive, cljs driven) blog post shows clojure.spec off a bit.
[1] - http://escherize.com/cljsfiddle/#gist=eea10854f99ef124f8dc152af1ff306d
[2] - http://blog.klipse.tech/clojure/2016/10/10/defn-args.html
There's a reason why "naming things" is one of the two hard problems in Computer Science. Data-Oriented Design (DOD) and Data-Oriented Programming (DOP) are two different things which has caused a fair amount of confusion on HN before. Data-Directed Programming (DDP) appears to be a third, different thing.
In searching those threads, I came across a post from the author of the DOP book describing the difference between DOD, DOP, and DDP (a different DDP! Data Driven Programing; a fourth thing!) [2], and I see he also made the "naming things" joke in the first paragraph, so I guess my humour isn't that unique!
There's been quite a bit of discussion about DOD and some about DOP (and much conflation between the two) on HN, it can be interesting to read [3].
1. https://martinfowler.com/bliki/TwoHardThings.html
2. https://blog.klipse.tech/visualization/2021/02/16/data-related-paradigms.html
3. https://hn.algolia.com/?q=Data+Oriented
For most things, yes. But this is JavaScript, the language where intransitive equality, implicit object-to-primitive casting and mutable global objects must be used in all slight-above-trivial code. Where `typeof` is useless and wrong, but nonetheless necessary; where there are seven different ways to parse a number, with six different semantics… there's a reason that “JavaScript: The Good Parts” is such a short book. https://blog.klipse.tech/assets/js_good_parts.jpg
Somebody who knows the good parts of JavaScript is a JavaScript expert. You want somebody who can write good JavaScript, and using the bad parts well has nothing on using the good parts adequately.