Emacs-like editors written in Common Lisp
cliki.net
cliki.net
There was no mention in the article of the LispWorks editor, that was derived from Hemlock. A really nice editor to use when I need the features of the LispWorks IDE, otherwise my favorite is just Emacs configured for LispWorks and SBCL.
For the discussion topic: I am not sure if the LispWorks editor is faster, snappier, etc. than Emacs because it is compiled Common Lisp.
From the homepage: "CLiki contains resources for learning about and using the programming language Common Lisp, and information about DFSG-compliant free software implemented in Common Lisp."
LispWorks is proprietary commercial software and thus out-of-scope for CLIKI.
Btw., that's a reason I don't contribute to CLIKI, as I'm not interested in only "DFSG-compliant free software implemented in Common Lisp".
That said, I am very fond of the undo-tree package for Emacs and I doubt I could switch to any editor that doesn't have something similar.
(edit: there's also https://github.com/nobody-famous/alive-lsp/ that is built for the Alive extension that brings great CL support to VSCode (usable but in the works right now).
In my eyes it is the more idiomatic implementation.
Undo-tree can also display the diff for each change. Useful when an operation induced changes in different parts of a long document (for example rerunning source code blocks with org-babel).
Vundo offers that functionality with Emacs' default undo tree, making it an objectively better package as it preserves undo-in-region, which undo-tree lacks.
It is an easy to install CL editor and REPL, so it's worth checking out for newcomers, it can help.
https://lispcookbook.github.io/cl-cookbook/editor-support.ht...
if yes, that's awesome, I'll look into it.
if no, what is the go-to? and is there an emacs-like using that lisp?
Common Lisp has everything Clojure has. It feels like Rich Hickie took everything that he liked about Common Lisp and put it into Clojure. Many of the functions in Clojure were basically copied from Common Lisp: if-let, conj(oin), disj(oin) are some examples of core Clojure functions and macros that were totally stolen from Alexandria.
Even better, most CL implementations can save directly to an executable file. Embeddable Common Lisp is my favorite because its executable files are measured in kilobytes, something I could never do with native-image. And the startup time is amazing.
I did look at other lisp languages when deciding to move away from Clojure. However, Racket's standalone executables (raco exe) include the interpreter, and so are huge; Chez Scheme's ecosystem doesn't have a YAML library as far as I can tell, ditto for Chicken. Also scheme's library ecosystem in general (sans racket) is a bit lacking to me.
Common Lisp it is. It has its warts, but they're not too bad. It's long history also speaks of stability though. SBCL is crazy good optimized.
I wrote a small program in CL and Rust, and (SB)CL can run faster than Rust EVEN FROM SOURCE! It's just completely mindblowing how fast it starts.
If you don't believe me, write a program that does something like count how many times each letter appears in a text file in CL and Rust, then run them with `time`. I can pretty much guarantee CL runs as fast or faster.
EDIT: my comment is meant for anyone curious about OP's clamis, I am obviously just agreeing with their point about CL's startup speed.
SBCL still needs garbage collection. There are also https://github.com/carp-lang/Carp and https://github.com/bakpakin/Fennel
I haven't used these. Would be great if low-level and embedded engineers could chime in.
BTW, since you program professionally in CL, do you use Emacs? Doom or custom?
Blog post about this will be written subsequently at https://blog.djha.skin .
1: https://git.sr.ht/~djha-skin/dotfiles/tree/main/item/dot-con...
2: https://git.sr.ht/~djha-skin/dotfiles/tree/main/item/dot-loc...
3: https://git.sr.ht/~djha-skin/dotfiles/tree/main/item/dot-scr...
I'm a vim user too, but recently I've been considering Common Lisp mainly due to this post: https://mikelevins.github.io/posts/2020-12-18-repl-driven/
so I did a brief tour on Emacs (cause everyone uses sly) but both Emacs and CL take too much time so I've postponed them.
Would be nice if you describe your vim+cl workflow and how does it hold up to Emacs+Sly+Org-mode ™
Clojure is a good choice if the JVM is an option. You get access to the entire Java ecosystem. It’s been years since I’ve worked in Java land, but my understanding is the JVM is pretty fast now too. I like Clojure and it’s the only Lisp I’ve ever been paid to work in. I already knew Java, so my Common Lisp experience made it extremely easy to pick up. If you want to write Lisp professionally it’s not your only choice, but it could be the best.
Scheme is more focused on functional programming. I’ve only ever used it for studying computing science. I don’t know much about Racket, but at a glance it looks like a kind of Scheme++.
As far as I know, GNU Emacs is the most popular editor for all of the above. It’s largely written in Emacs Lisp, but the core and parts where performance is critical are C. Racket does come with its own editor, DrRacket, so maybe Racket users use that? I don’t know if it’s written in Racket but I’d suppose it is.
Incidentally, it’s my understanding that the Nyxt browser team intends to add full editing support at some point. If so, it will be a kind of web focused Emacs, which sounds interesting.
I use a mix of DrRacket, WinEdt and Geany (with more color in the matched parenthesis).
Guile is GNU's common language runtime, sorta like Java's JVM or Microsoft's CLR. And Scheme is really the only first-class language of Guile; to a lot of people "Guile" means "Scheme". I don't know of an Emacs-like using Scheme, but there is an effort to implement Emacs-Lisp on Guile, and have GNU Emacs ditch its Lisp interpreter in favor of Guile. This would allow Emacs to use any language that can run on Guile... which mostly means Scheme.
That Python is the most popular language today should tell you how successful Guile has been at this goal.
* See https://practical-scheme.net/gauche/man/gauche-refe/Library-... for an overview.
My implementation strategy would probably be to start by using FFI to reuse as much of the C code as possible and then incrementally rewrite it. Or not, maybe that wouldn’t even be necessary.
Yes, they are different languages, working atop different platforms. They have different semantics, vastly different core libraries, etc. Yet at the same time, somehow, there's little mental overhead when switching between them.
I don't have any difficulties moving between Fennel, Clojurescript, Clojure, Clojure-Dart, LFE. But if I had to manage writing code and maintain multiple projects in Lua, Javascript, Java, Erlang and Dart - I would claim that my name is Guy Stele Jr. and I am a very smart programmer. Alas, I'm not that smart, that's why I chose Lisp.
While you can compare Scheme to Clojure and Clojure to Racket, Common Lisp embodies the alternatives against which each was developed.
Clojure doesn't have an Emacs-like but it does have Cursive (for IntelliJ) and CIDER (for Emacs, like SLIME).
Scheme has Guile Emacs (currently in an unfinished state, needs fiddling to even build) and Edwin (comes with MIT/GNU Scheme).
If you wish to "look into" Lisp, do the work: look at a bunch of resources, skim them, pick the ones that look intersting.
Asking whether to look into something is sometimes just a way to procrastinate. Questions like yours (not just about Lisp, but definitely about Lisp as well) are asked every day, and answers are (i) repetitive and (ii) abound. Just do the work.
so first, yea bad phrasing, but that question usually implies "majority of people".
second, I have done work. I have coded even stuff in clj and cljs. little elisp. but I am not in contact with anyone doing lisp so I am disconnected from the "lisp community". hence my question.
in any case, my question still stands, but this time as "I'd love to get some opinions about lisps being used nowadays, and if there are emacsen in those".
There is no "Lisp community". In this family of languages, there are a bunch of individuals that sometimes form communities around areas of interest or particular fora.
If you looked into Clojure and Elisp, looking into Common Lisp or some Schemes could still be valuable, sure. All of them are in use. You can visit the relevant subreddits or chat channels or mailing lists to "get connected". Maybe even find some meetups or submit pull requests.
As far as I know there are no Emacsen in popular use today except GNU Emacs. There are some editors "inspired" by Emacs that are developed and possibly used by a few. These may be interesting and you may find them usable, but I'm not sure their authors would consider them part of the family of Emacsen just yet.
Compare this to other popular languages from C++ to Python, which surely generate tons of additional work by continually changing the languages themselves.
It would also be nice to see a greater adoption of "sequence" (which has a limited set of things that qualify) being opened up so that user-defined sequences could be used with existing sequence processing functions. Same for numbers and other things. Allowing (performance is a valid concern here, though) more generic functions would open up more interesting developments later. See Julia and its application in the numerical computing domain. You can do that kind of computing in CL, but you can't use the existing arithmetic and numeric functions because they're only generic to the limit of the defined numeric tower and can't be extended beyond that.
Concurrency, totally absent in the language standard, for better or worse. On the one hand you don't necessarily want to bless a particular concurrency model, and Common Lisp is nothing if not a toolbox language (pick your base capabilities and grow it to fit your application). So you'd want some low-level primitives that can be composed rather than blessing one or two particular models. But without standardization, this isn't happening. You do have Bordeaux-threads which basically gives you a portable threads interface by mapping to each CL implementation's specific threading library. But threads can be heavyweight compared to other options, and BT limits you to the lowest common denominator across the implementations. People have built useful abstractions on top of it, still. And some implementation could always implement something like coroutines and a thread pool for distributing them, but it would be implementation specific rather than standard. Even having that as a baseline model, leaving specifics of implementation open but locking down semantics, would be a good development for CL.
And Lisp is almost uniquely able to handle transitions to later standards as I described above. You don't actually have to forfeit backwards compatibility entirely or at all if the changes are handled by moving to a new default base package. :cl-user/:cl become :cl##-user/:cl##. Accessing old features is still feasible.
Go use cl21[0] if you care for this sort of thing.
> more generic functions would open up more interesting developments later
generic-cl[1]. But in a prefix-oriented language, I just don't see this as particularly important.
> you don't necessarily want to bless a particular concurrency model
You do[2]; this is one of the notable deficiencies in the cl standard that really bites, today. It is being worked on.
Right, it demonstrates what I'm saying about the relative ease for CL to move forward. You'll still need to bring the implementations onboard though to be really successful. See the note in the generic-cl link about a potential performance hit (and then how to work around it) because of increased use of generic functions. Implementations can improve their performance around generic functions and method dispatch, but users (like those developing cl21 and generic-cl) aren't going to do so on their own as easily or portably. Having an actual collective standards body working on a real cl2x standard would be critical to getting all implementations moving on this.
> You do[2]; this is one of the notable deficiencies in the cl standard that really bites, today. It is being worked on.
Are all implementations moving towards some common better approach today? Or are we still stuck with bordeaux-threads (and anything built on that) as pretty much the only portable way to do concurrency in CL?
What I mean by blessing a particular model, though:
Do you use a shared-nothing BEAM style? Mailboxes per process (what is a process?)? Channels that can be passed around? Coroutines? Asyncio style? Structured concurrency? None of the above? All of the above?
CL has always been a toolbox language, many of the things programmers use actually map down to more primitive elements (even defun is a macro and you can provide your own, see SERIES and SCREAMER for examples). So instead of presenting a high-level Go-styled concurrency model or insisting on structured concurrency it would be more in keeping with CL's history to provide the baseline features that enable better concurrency (and uniform across implementations) and then let people build on that. Higher level libraries can come along later (see how CLOS came out of earlier developments like Flavors and CommonLoops), and maybe one of those can be blessed by becoming part of the standard. But the primitives will remain so variations will remain possible for those who want them.
So, what you actually want is that doing this could be done in a way that everything is as efficient as if one invoked the CL built-in functions. I think a little more smarts in CL compilers could do this, in particular efficient invocation of generic functions when the argument classes are known at compile time (doing this in a way that allows methods to be added or redefined requires some care but can be done.)
There is a general philosophy in the design of Common Lisp: expose to the user facilities that are used by an implementation for the implementation of built-ins. I don't think Common Lisp is quite complete in this respect, but this would be the place to extend it.
Given that, I think for Elisp to still come at #25 in this metric is a huge credit to its ecosystem for sure, but I still think that puts into perspective how much of a non-entity Common Lisp has become.
I've been using croatoan for a ncurses text interface, but I fear that i'll need to write something more "guish" in the next few months for the terminal afraid.
(Miror si haec prima flammae latinae in interrete est.)
Heh.