A project to rewrite the ClojureCLR engine.
Persistent vectors, Part 4 -- Performance
This is the first data structure we’ve worked on where performance can reasonably be tested. How does the new F# version of the code compare to the original C#? Where can performance be improved?
Persistent vectors, Part 3 -- Transiency
Clojure’s vectors, hash-maps and hash-sets support transients. We examine the implementation of transiency for
Persistent vectors, Part 2 -- Immutability and persistence
An implementation of a vector class that is immutable, persistent, and efficient takes some non-trivial machinery. It’s time to go deep.
Persistent vectors, Part 1 -- The landscape
This is the first of a series of posts on the design and implementation of
PersistentVector, an immutable, persistent vector class supporting a transient mode for efficient batch operations.
You can be a boss at reducers if you know this one weird trick!
Laziness and chunking
Laziness is a central concept in the handling of sequences in Clojure. Chunking comes along as an efficiency measure. Surprisingly, at the level of implementation we are looking at it, very little needs to be done; laziness is defined most in the Clojure code that builds
clojure.core. We’ll take a look at what is needed at the bottom to support laziness and chunking.
A road to maps
I’d like to draw a roadmap for how to approach implementing the remaining collections.
We have working code.
Doing a number on Numbers
Actually, more like
Numbersdid a number on me. But we’re good friends now.
Numbersis ready to go. This is a long post;
In which I contemplate the meaning of
Sequential. This is an easy one compared to what you just went through.
A numbers game
Getting started implementing Clojure collections requires methods in
clojure.lang.Utilfor operations such as equality testing and hashing. These methods must operate properly on numeric types. The machinery for this is the class
Making a hash of it
Wherein I look at hashing and equality in Clojure.
Circular reasoning (part 2)
The code with the greatest entanglement across the Clojure codebase comes in the static classes
clojure.lang.Util. How can these classes be restructured to reduce cyclic dependence and improve clarity?
Circular reasoning (part 1)
I have to analyze the nature of circular references in the current Clojure implementations in order to avoid making an inelegant F# monolith – massive quantities of code in one file with all the types mutually recursive.
This map is the territory
Maps are hugely important in Clojure programming. Internally, they are supported by a specific group of interfaces. Here we will examine these interfaces and provide an incredibly naive implementation. The intention is to make clear the mechanics of these interfaces in a simple setting. Later, when we implement realistic maps, we can wave at this stuff in passing and focus on the intricacies of the data structures themselves.
Now for some homework. Let’s see how well you absorbed the material in the previous post.
A minimal implementation of Cons
Seeing the complexity of the Clojure interface/data-structure ecosystem as we did in the last post can be a bit daunting. But if we start gently we can tease out some of the basic interactions and techniques that underlie how the real Clojure versions of these data structures are implemented.
For your Cons-ideration
To build a Lisp, you could perhaps start with the simplest data structure, the cons cell: a simple record structure with two fields that hold pointers and a staple of Lisp implementation from the beginning.
The plan of attack
One does not simply start writing a Clojure implementation. One needs a plan.
ClojureCLR -- Reconsidered
Introducing a project to rewrite ClojureCLR – ClojureCLR.Next. With this blog, I hope to record some of the thinking I go through in the process, for myself mostly but perhaps for a future maintainer of the project.
subscribe via RSS