I poked around a bit to figure out why this was even posted and there was a new release 1.6.0 on November 22nd which adds support for jdk 11, among other minor things. ABCL provides a java class which can load/eval lisp code, and the ability to call java classes from your lisp program, stuff like that.
public final class Cons extends LispObject
{
public LispObject car;
public LispObject cdr;
}
I would have thought it would provide that abstraction to the programmer but use another representation internally. Chasing pointers like this on modern hardware is surely crazy?
We're using object-oriented languages like Java on modern hardware, so pointer chasing is quite natural. Typical Java programs will do that all the time. In many ways the Java runtime is relatively similar to a Lisp runtime - it's just not tailored on the low-level to Lisp - for example cons cells for linked lists are not provided on the virtual machine level.
Since lists in typical Lisp implementations are made with cons cells, some form of two element data structure is needed. Using Java objects has the drawback, that this is not the most efficient representation.
Good Lisp implementations typically make sure that the cons cell has very little overhead:
* cons cells are just objects made of two memory words without type tag. The tag is encoded in pointers to these cons cells.
* cons cells can directly encode some simple data like fixnum integers, characters, ...
* cons cells might be allocated in special memory regions and GCs might take special care
OTOH, more efficient low-level representations like CDR-coding, which allows some lists to be represented in vector like ways is mostly not used in current implementations, since it was not see worth the effort anymore - it was thought worth on older systems with much small main memories than we have today. Smaller main memories than the caches on a modern CPU.
In addition to cons cells being forced in some scenarios, this is Common Lisp, not Lisp 1.5: Programmers who want performance for linear collections are expected to use data types like vectors, which are primitive and not implemented in terms of cons cells at all.
> Vectors are Common Lisp's basic integer-indexed collection, and they come in two flavors. Fixed-size vectors are a lot like arrays in a language such as Java: a thin veneer over a chunk of contiguous memory that holds the vector's elements.2 Resizable vectors, on the other hand, are more like arrays in Perl or Ruby, lists in Python, or the ArrayList class in Java: they abstract the actual storage, allowing the vector to grow and shrink as elements are added and removed.
Because CONS cells aren't used only for lists, but are fundamental data type used as building blocks for few other things.
As such, they are required to hold any value or reference possible, and aren't exactly amenable to different format.
There is one technique which had somewhat large use, CDR-coding, based in the idea that you can tag a cell in a way that tells the system that the next field isn't a reference to a CONS cell, but the CAR of one, and thus linearize lists in memory. However, doing it fast requires a custom cpu so you can resolve this fast in transparent way, as well as it turned out to not give much benefit. However, widening gap between cpu and memory might make it attractive again...
A lot of things in Lisp force the implementation of lists as cons cells. It’s probably possible to do something different, but no one has, and the result won’t be a Common Lisp.
(Consider that the detail of improper lists is enshrined in the language.)
Last I heard (years ago), some Lisp implementations had tried using arrays for non-branching cons chains, but found that performance wasn't actually better than actual conses in general.
The title of this post should be changed to "Armed Bear Common Lisp - Common Lisp on the JVM." It's an iconic name, and then people would actually know what the post title was referring to.
A bit off topic, but is Common Lisp still a good choice?
I spent a lot of time learning and coding CL during the last decade. I love lots of things about the language. Overall, it's great it's true multiparadigm. Few languages achieve that.
However, the implementations are too fragmented which makes the standard quite stagnant. And libraries are falling a bit behind.
I love Clasp is putting CL on top of LLVM. I wish we could have something with the best ideas of Racket, Clojure and CL on the LLVM.
Good choices depend heavily on circumstances, so, what are you trying to do, for how long, and with whom? Even if what you're trying to do isn't programming per se, but something like betting on how you'll make programming related money in the future, it matters to specify what exactly it is you're trying to do before you evaluate the choices.
I think at least it's hard to argue CL would be a bad choice in general, and it's certainly proved itself over the decades in many domains and circumstances... But there are always tradeoffs, and other languages can be better choices when circumstances push different ones.
A particular blog post that gets passed around (you may very well have seen it) is https://www.darkchestnut.com/2017/pragmatic-reasons-for-choo... It's just an example of the process, but it's still valid. His list of requirements might not be your list, or your weighting might be different. (It's been fun reading tweets from https://twitter.com/rainerjoswig this month just to appreciate how portable CL code is across CPU architectures and implementations and if you value that a lot why wouldn't you consider CL very highly; meanwhile others don't value portability and are fine with an effectively iOS-only language or whatever.)
I don't really follow your statement about implementations being fragmented --> stagnant standard. The standard is the standard, it's as immutable as C89. Or do you mean you're sad that there's unlikely to be a new revision to the standard that all the implementations will adopt, unlike C99 and beyond (which still isn't fully supported by all the big players)? That's understandable, but you probably used the portable libraries that offer the big things one might want from a new standard, so...
Clojure with a good c (stretch goal: c++) FFI on LLVM would be amazing. I somehow suspect the reason we don’t have it in a fully baked form is that it’s hard.
Racket is also lovely, and I hope that their port to Chez Scheme will enable alternative implementations, since more of Racket is now written in Racket rather than c.
I think it is. A lot of the 'stagnation' is due to the fact that the standard is a standard, so Lisp implementations aren't changing the definition of characters willy-nilly — and so code written twenty years ago is still correct and performant enough, so there's no need to update it.
I would love to see a slightly more modern CL, but it's good enough to get work done, and it's still light-years ahead of everything else.
I would say it is not a good choice today, unless you have a legacy code base in CL.
There are more modern Lisps which have a much better concurrent programming story — which is why after years of working in Common Lisp I switched to Clojure.
The other huge advantage of Clojure is ClojureScript: most of my business logic code these days compiles to both Clojure and ClojureScript, which is important for modern applications and lets me keep my line count low.
>A bit off topic, but is Common Lisp still a good choice?
As always, it depends on your application. For instance I decided recently that I would work my way through the cryptopals challenges, and opted to avoid Lisp since bit-twiddling is such a pain in that language.
If you don't want to learn emacs, Sublime + the Sublime REPL package is quite nice. I've n using it to write SBCL but it can also use ABCL. Also REPLs for lots of other languages.
I'm using Vim with the SLIMV plugin (derived from SLIME for Emacs) and a bit of script glue to open a new Terminal tab for running SBCL with SWANK in. Like an IDE, and connected with a live Lisp.
[+] [-] owyn|6 years ago|reply
https://abcl.org/svn/tags/1.6.0/CHANGES
As an "old" I learned LISP in college but have never had the opportunity to use it in my career. Still on my todo list!
[+] [-] awayfromhomenow|6 years ago|reply
[+] [-] dang|6 years ago|reply
Just this from 2009: https://news.ycombinator.com/item?id=930514
and a bit from 2017: https://news.ycombinator.com/item?id=14605334
[+] [-] lispm|6 years ago|reply
[+] [-] chrisseaton|6 years ago|reply
[+] [-] lispm|6 years ago|reply
Since lists in typical Lisp implementations are made with cons cells, some form of two element data structure is needed. Using Java objects has the drawback, that this is not the most efficient representation.
Good Lisp implementations typically make sure that the cons cell has very little overhead:
* cons cells are just objects made of two memory words without type tag. The tag is encoded in pointers to these cons cells.
* cons cells can directly encode some simple data like fixnum integers, characters, ...
* cons cells might be allocated in special memory regions and GCs might take special care
OTOH, more efficient low-level representations like CDR-coding, which allows some lists to be represented in vector like ways is mostly not used in current implementations, since it was not see worth the effort anymore - it was thought worth on older systems with much small main memories than we have today. Smaller main memories than the caches on a modern CPU.
[+] [-] msla|6 years ago|reply
http://www.gigamonkeys.com/book/collections.html
> Vectors are Common Lisp's basic integer-indexed collection, and they come in two flavors. Fixed-size vectors are a lot like arrays in a language such as Java: a thin veneer over a chunk of contiguous memory that holds the vector's elements.2 Resizable vectors, on the other hand, are more like arrays in Perl or Ruby, lists in Python, or the ArrayList class in Java: they abstract the actual storage, allowing the vector to grow and shrink as elements are added and removed.
[+] [-] p_l|6 years ago|reply
As such, they are required to hold any value or reference possible, and aren't exactly amenable to different format.
There is one technique which had somewhat large use, CDR-coding, based in the idea that you can tag a cell in a way that tells the system that the next field isn't a reference to a CONS cell, but the CAR of one, and thus linearize lists in memory. However, doing it fast requires a custom cpu so you can resolve this fast in transparent way, as well as it turned out to not give much benefit. However, widening gap between cpu and memory might make it attractive again...
[+] [-] ts4z|6 years ago|reply
(Consider that the detail of improper lists is enshrined in the language.)
[+] [-] ken|6 years ago|reply
[+] [-] JimmyRuska|6 years ago|reply
kawak - scheme for the JVM https://www.gnu.org/software/kawa/
bigloo is a scheme can compile to C. I think it can also make java class files with bindings https://www-sop.inria.fr/mimosa/fp/Bigloo/
[+] [-] Per_Bothner|6 years ago|reply
(There is actually a very-incomplete Common Lisp implementation as well in Kawa, but the Kawa Scheme dialect is the main Kawa language.)
(Hoping to make an official Kawa 3.1 release by the end of the year - but no promises. Until then, use git HEAD.)
[+] [-] kick|6 years ago|reply
[+] [-] dang|6 years ago|reply
Seems like we've had about 60 posts as Armed Bear: https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
and 200 as ABCL: https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
[+] [-] twic|6 years ago|reply
[+] [-] nothrabannosir|6 years ago|reply
Ahh, HN - never change. Sorry I mean, Hacker News - never change. :)
[+] [-] nextos|6 years ago|reply
I spent a lot of time learning and coding CL during the last decade. I love lots of things about the language. Overall, it's great it's true multiparadigm. Few languages achieve that.
However, the implementations are too fragmented which makes the standard quite stagnant. And libraries are falling a bit behind.
I love Clasp is putting CL on top of LLVM. I wish we could have something with the best ideas of Racket, Clojure and CL on the LLVM.
[+] [-] Jach|6 years ago|reply
I think at least it's hard to argue CL would be a bad choice in general, and it's certainly proved itself over the decades in many domains and circumstances... But there are always tradeoffs, and other languages can be better choices when circumstances push different ones.
A particular blog post that gets passed around (you may very well have seen it) is https://www.darkchestnut.com/2017/pragmatic-reasons-for-choo... It's just an example of the process, but it's still valid. His list of requirements might not be your list, or your weighting might be different. (It's been fun reading tweets from https://twitter.com/rainerjoswig this month just to appreciate how portable CL code is across CPU architectures and implementations and if you value that a lot why wouldn't you consider CL very highly; meanwhile others don't value portability and are fine with an effectively iOS-only language or whatever.)
I don't really follow your statement about implementations being fragmented --> stagnant standard. The standard is the standard, it's as immutable as C89. Or do you mean you're sad that there's unlikely to be a new revision to the standard that all the implementations will adopt, unlike C99 and beyond (which still isn't fully supported by all the big players)? That's understandable, but you probably used the portable libraries that offer the big things one might want from a new standard, so...
[+] [-] peatmoss|6 years ago|reply
That said, there is Ferret which is Clojure-like, and compiles to c++: https://ferret-lang.org/
Racket is also lovely, and I hope that their port to Chez Scheme will enable alternative implementations, since more of Racket is now written in Racket rather than c.
[+] [-] earenndil|6 years ago|reply
Clasp is nice, but SBCL is fast enough that it's mostly extraneous unless you really need to talk to c++ code.
[+] [-] zeveb|6 years ago|reply
I would love to see a slightly more modern CL, but it's good enough to get work done, and it's still light-years ahead of everything else.
[+] [-] jwr|6 years ago|reply
There are more modern Lisps which have a much better concurrent programming story — which is why after years of working in Common Lisp I switched to Clojure.
The other huge advantage of Clojure is ClojureScript: most of my business logic code these days compiles to both Clojure and ClojureScript, which is important for modern applications and lets me keep my line count low.
See my Quora answer (from several years ago, so some things have changed) for more on why I switched: https://www.quora.com/What-do-veteran-Lisp-programmers-think...
[+] [-] na85|6 years ago|reply
As always, it depends on your application. For instance I decided recently that I would work my way through the cryptopals challenges, and opted to avoid Lisp since bit-twiddling is such a pain in that language.
[+] [-] edko|6 years ago|reply
[+] [-] Arcsech|6 years ago|reply
[+] [-] potta_coffee|6 years ago|reply
[+] [-] jimws|6 years ago|reply
[1] https://news.ycombinator.com/item?id=21735148
[2] https://susam.in/blog/lisp-in-vim-with-slimv-or-vlime/
[+] [-] tempodox|6 years ago|reply
https://github.com/kovisoft/slimv