Hello,
Several months ago I forked this repo and started working on it. After some additions, I found myself unable to work with such a large codebase with which I was so unfamiliar, so I decided to try starting from scratch, borrowing some pieces from your project. I expected this to be something I played with for a week then forgot about, but I ended up spending a great deal of my free time working on it, and have made a lot of progress. I had assumed this project was abandoned so I didn't feel the urgent need to contact you, but now that I see you're still maintaining this project I'd like us to collaborate.
Some of the more significant things my version has (not sure which of these are also in yours):
true (distinct from cl:t), false, and empty list (both distinct from cl:nil)
- persistent lists
- persistent vectors (based on your implementation), and persistent maps and sets (based on cl-hamt)
IMeta, IHashEq, IReference and many other interfaces from Clojure's java source
- Currently all implemented with
cl:defclass, ideally these would be defined with defprotocol
- destructuring, both for maps and sequences
loop, but using labels so that TCO is performed by the compiler, and no check is performed to ensure it's used properly
- Note: I have toyed with a version using
tagbody, which works fine, but also doesn't confirm that recur is in tail position
fn, supporting multiple arities, a name, and recur within the bodies
- normally a regular function is returned, but using
with-meta on it upgrades it to a Fn.
for (producing an actual lazy-seq)
- A readtable with map, set and vector literals, #_ to discard next sexp, @ to deref, ^ for metadata, #() for functions
- This readtable is a bit hacky, but I'm also testing one that parses forms into clojure data structures, and supports syntax-quote (including ~@ with any
Seq, and auto-gensym# syntax). It seems to work pretty well.
reduce, transduce, and many, if not most, transducers from Clojure.core implemented
- Atoms, Namespaces, Vars
- Not tested in depth. Vars are probably in the most complete state of the three.
- Vars are funcallable, and #' syntax for vars works, because
def sets the symbol's value a la cl:defvar, and sets the symbol's function to a Var. The Var's funcallable-instance-function just applies its value to the arguments.
- A lot of scaffolding for Agents
- If I remember correctly they do work fairly well, but the STM has to be developed before moving forward
Symbols and Keywords, distinct from CL keywords and symbols
- this part's really tricky, and my glue code between the two is very shoddy
= (it works okay, still plenty of work to be done)
- Pretty printing vectors, sets, maps, namespace qualified
Vars, Symbols and Keywords, etc.
- A ton of other clojure.core functions and macros
I think that's most of the major developments. Some major roadblocks I've realized while working on this:
- Atoms. The only free/libre CL implementations that support CAS on struct/object slots are SBCL and ECL. This means that these are probably the only dists that can be targeted
- Additionally, ECL (somehow) seems to not support timeouts in any form (needed for
deref), so it may also not be a viable platform, leaving just SBCL
- variadic functions. In CL, the
&rest arg must be a proper list. In Clojure, an & arg can contain any ISeq (from what I can tell). Converting every ISeq to a proper list won't do either, because in Clojure you can apply functions to infinite lazy sequences.
- monitors. every
Object in java, and consequently all data in Clojure, can function as a monitor, and the locking macro can be used to synchronize code around an object. I have no idea how to make (locking 3 ...) work in CL.
- thread local bindings. From what I can tell, in SBCL the only way to establish thread local bindings is via a
let in the thread's function, but documentation on this is practically non-existent. push-thread-bindings and co may need to be manually implemented with hash-tables/maps or similar.
If you'd like to merge the projects then let me know and I can put my repo on GitHub and we can figure out how to fit the pieces together (but I must warn you that I'm very busy and generally suck at responding)
Thanks
Hello,
Several months ago I forked this repo and started working on it. After some additions, I found myself unable to work with such a large codebase with which I was so unfamiliar, so I decided to try starting from scratch, borrowing some pieces from your project. I expected this to be something I played with for a week then forgot about, but I ended up spending a great deal of my free time working on it, and have made a lot of progress. I had assumed this project was abandoned so I didn't feel the urgent need to contact you, but now that I see you're still maintaining this project I'd like us to collaborate.
Some of the more significant things my version has (not sure which of these are also in yours):
true(distinct fromcl:t),false, and empty list (both distinct fromcl:nil)IMeta,IHashEq,IReferenceand many other interfaces from Clojure's java sourcecl:defclass, ideally these would be defined withdefprotocolloop, but usinglabelsso that TCO is performed by the compiler, and no check is performed to ensure it's used properlytagbody, which works fine, but also doesn't confirm thatrecuris in tail positionfn, supporting multiple arities, a name, andrecurwithin the bodieswith-metaon it upgrades it to aFn.for(producing an actual lazy-seq)Seq, andauto-gensym#syntax). It seems to work pretty well.reduce,transduce, and many, if not most, transducers from Clojure.core implementeddefsets the symbol's value a lacl:defvar, and sets the symbol's function to a Var. The Var's funcallable-instance-function just applies its value to the arguments.Symbols andKeywords, distinct from CL keywords and symbols=(it works okay, still plenty of work to be done)Vars,Symbols andKeywords, etc.I think that's most of the major developments. Some major roadblocks I've realized while working on this:
deref), so it may also not be a viable platform, leaving just SBCL&restarg must be a proper list. In Clojure, an&arg can contain anyISeq(from what I can tell). Converting everyISeqto a proper list won't do either, because in Clojure you can apply functions to infinite lazy sequences.Objectin java, and consequently all data in Clojure, can function as a monitor, and thelockingmacro can be used to synchronize code around an object. I have no idea how to make(locking 3 ...)work in CL.letin the thread's function, but documentation on this is practically non-existent.push-thread-bindingsand co may need to be manually implemented with hash-tables/maps or similar.If you'd like to merge the projects then let me know and I can put my repo on GitHub and we can figure out how to fit the pieces together (but I must warn you that I'm very busy and generally suck at responding)
Thanks