ClojureCLR.Next
A project to rewrite the ClojureCLR engine.
Posts
Qualified methods -- for ClojureCLR
Clojure has introduced a new qualified methods feature allows for Java methods to be passed to higher-order functions. This feature also provides alternative ways to invoke methods and constructors, and new ways to specify type hints. We need to enhance this mechanism for ClojureCLR in the same ways we enhanced ‘classic’ interop.
What's the point? BigDecimal in review
More to the point: Where’s the point? Recently I had to dig into the
BigDecimal
implementation to fix a reported bug. Every time I have to look at theBigDecimal
code, it is a journey of rediscovery. I’m going to write down a few things to save me some time in the future.PersistentHashMap, part 5 -- At a loss
We look at performance of the new F# version of
PersistentHashMap
and compare it to the Clojure version. And in the end, declare ourselved mystified.PersistentHashMap, part 4 -- Other matters
We continue our discussion of
PersistentHashMap
with a discussion of transiency and alternative F# coding techniques.PersistentHashMap, part 3 -- The guts
We take a look at the internal nodes that implement the core algorithms of the
PersistentHashMap
data structure.PersistentHashMap, part 2 -- The root
I’ll sketch the code for the root of the
PersistentHashMap
structure in this post. The focus is on the data structures used and the primary operations: adding a key/value pair, find the value associated with a key, and removing a key. We’ll start with the Clojure interfaces that must be implemented.PersistentHashMap, Part 1 -- Making a hash of things
The first of several posts on implementing immutable, persistent Hash Array Mapped Tries. This post describes the data structure at a high level; subsequent posts will provide F# code for the base implementation and then discuss transiency.
Corrigendum -- Static initialization
I must have made an error benchmarking static initialziations, detailed in a preceding post. Here I do a little more analysis and provide a correction to my comments and to the code.
A mega-dose of micro-benchmarks, Part 3 -- Finishing touches
We apply some finishing touches to the
PersistentArrayMap
creation code. And then declare success.A mega-dose of micro-benchmarks, Part 2 -- by the numbers
Improving the numerics code for type mapping, operations lookup, and conversions.
A mega-dose of micro-benchmarks, Part 1 -- Setting the stage
We go deep doing micro-benchmarks to improve the performance of one little function.
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
PersistentVector
.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.Reductionism
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.
First code
We have working code.
Doing a number on Numbers
Actually, more like
Numbers
did a number on me. But we’re good friends now.Numbers
is ready to go. This is a long post;Numbers
is big.con-Sequential objector
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.Util
for operations such as equality testing and hashing. These methods must operate properly on numeric types. The machinery for this is the classclojure.lang.Numbers
.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.RT
andclojure.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.
Odd questions
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