Readit News logoReadit News
agentkilo · 8 months ago
SBCL is a great choice! It's a surprisingly dynamic system (so are other CL implementations).

A while ago, I did some private work for someone, using SBCL, and sent her the native binary I built, then forgot about the whole thing.

The client came back with some new requirements much later, when the project was concluded, and the source code was already lost by that time.

I vaguely remembered how I did things, so I spawned a REPL from the old binary, went into the relevant CL package, wrote a new function that overrides the old behavior, and the client's problem was solved.

I did all those without the original source code. It was a small thing to fix, but I can't imagine making the same fix so swiftly with any other tech stack, when the source code is lost. I was deeply impressed.

chikere232 · 8 months ago
That's pretty cool, but also, get version control
pizza · 8 months ago
Version control won't help if the repo itself has been lost to the sands of time
f1shy · 8 months ago
Agree, but I think in this case would not help. It was not that a version was lost, but all. Had they had VC, probably the repo would have been deleted.
munchler · 8 months ago
You don’t deliver source code with the binary at the end of the project?
coldtea · 8 months ago
Many don't.
smokel · 8 months ago
This is something I really like about Common Lisp, but after ~30 years of progress, I am a bit disappointed with improvements in the field of interactive development.

The process you describe is possible in JavaScript and many other languages as well. Updating a JAR is trivial, but doing it in a running system is uncomfortable.

The first thing to start with is versioning at the function, class, package, or module level. Combine that with versioning of data, and you've got my interest :)

pjmlp · 8 months ago
JRebel, for those willing to pay.
lenkite · 8 months ago
When will the next standard of Common Lisp be released ? 1994 is really showing is age.
nomilk · 8 months ago
Looks like vim-slime is essential to how you work with CL + vim. I've only used vim for not even 2 years, and came across vim-slime 6 months ago when working in ruby and wanting to quickly 'send' code from editor (neovim) to rails console. 2 months ago I launched a startup and for hours every day had to swat/fix repercussions of bugs that weren't apparent pre-launch (as well as doing via the console things users needed but weren't able to do because the feature to do it hadn't been built yet). It was daunting. I don't know how I'd have managed without vim + vim-slime. Probably a lot of copy/pasting from vscode. Vim + vim-slime was at least a 2x productivity improvement, and >2x increase in developer happiness.

Another huge benefit of vim and vim-slime is it is immediately valuable when you use/learn any new language. So long as the language has a REPL/console/interpreter that can be opened from the terminal or terminal emulator in any form (e.g. CL, ruby, python, bash etc etc etc) then vim + vim-slime will be a brilliant ~IDE. (Possibly the only thing I haven't been able to do but wanted to is 'send' code from neovim to the javascript console in chrome, which would be pretty awesome!)

A side note: I found doom-emacs very similar to vim, only needed ~10 or so new keyboard shortcuts to be productive in emacs. (I still much prefer vim, but I'm not so down on emacs).

ofalkaed · 8 months ago
>Looks like vim-slime is essential to how you work with CL

slime has some issues for me (obviously not OP) and I am not convinced lisp and vim are a good pair. lem is getting pretty good and improving by the day, find it much better to work with than vim when it comes to lisp and vim is my primary editor.

https://github.com/lem-project/lem

djtango · 8 months ago
I have been using Clojure and before that Racket using only vim and vim-surround for almost a decade now.

I am sure I have left some productivity on the table not investing in workflows like cider etc but I have gotten a decent workflow using just vanilla tmux, a repl pane and vim-surround

The % matcher in vim does so much heavy lifting, I've never felt limited by a lack of slurp and barf

I actually wrote my own tiny plugin to send snippets to the repl using nc and I'm still happy enough tearing the clojure repl up and down and copying stuff in by hand because dealing with repl state can be pain. Even though I have at times had repls open for months, there is a freedom in just tearing it all down and up again.

Clojure itself has plenty of functions to load in files or snippets to help as well

quesera · 8 months ago
> I don't know how I'd have managed without vim + vim-slime.

This is interesting -- I've worked with people who swear by common lisp, emacs, and SLIME.

I'm happiest with ruby and vim, but I have not tried vim-slime (nor even heard of it before, so thank you!).

But FWIW, my strategy for running larger bits of ad hoc code on the ruby/rails console is to:

  1. Add the code to a persistent local file (e.g. "ops_console_tools.rb")
  2. scp the file up to the target machine where I am running the irb/pry console
  3. In the console, run `load '/PATH/TO/ops_console_tools.rb'`
  4. Run the new code: `Ops::User::CustomReport.run(90.days.ago..)`
To keep things a bit more sane, all of the ad hoc ruby code is in modules, e.g. `Ops::User`.

And it helps to include some code to clear constant definitions which would otherwise complain to STDERR if you update and reload the file multiple times.

None of this is as awesome as SLIME of course, but it's pretty tolerable with a bit of readline-style up-arrow and command-history conveniences.

Disclaimer: Of course, running ad hoc code in prod is frowned upon. But we're extolling the virtues of CL in this thread, so I'll confess to breaking best practices in environments where it's permissible! Also this process gives you syntax highlighting while editing without requiring config on target host, and you can include the file in version control for greater formality.

pritambaral · 8 months ago
I replaced a similar workflow with SLIME-style `eval-defun` by just running the remote Ruby console within emacs, using inf-ruby. Combined with robe, you get code intelligence for free, but without the heavy and error-prone static indexing of Solargraph or Ruby-LSP.
tempodox · 8 months ago
Yep, I'm using the `slimv` plugin for vim and the `swank` server in a running `sbcl` instance in a second terminal tab. Since I'm on macOS, I could build a keyboard shortcut in vim that automates opening the 2nd terminal tab with the “Lisp machine + swank” when I say “connect” in vim. slimv/swank practically make vim an IDE for Lisp.
ferfumarma · 8 months ago
How do you learn vim-slime? I have used vim before, so I have basic skills there, but I get lost and run out of time when I try to figure out how the slime model works and how to create a lisp project.

Is there a tutorial you followed or a video you found useful? What was your starting fund of knowledge?

nomilk · 8 months ago
Great question - it's shocking easy to learn. Just three steps 1. Install (via vim-plug, lazy.nvim, or whatever vim plugin manager you're using), 2. configure it. Depending on your terminal the instructions are a little different, but it should only take a few moments due to the brilliant instructions found here: https://github.com/jpalardy/vim-slime/tree/main?tab=readme-o... I use kitty so I add two lines to kitty.conf and it's all ready to go. But it will depend on your terminal/terminal emulator. The instructions in the readme should have you covered.

Then 3. use it. This is shockingly easy, open two panes in your terminal with neovim on one side and REPL/interpreter on the other. For example I have neovim with my ruby file on the left pane and a rails console on the right (but on the right could be SBCL, python interpreter, or any other interpreter). In neovim, move the cursor to the line you want to run and press ctrl + c twice in quick succession. It will 'send' that line to the interpreter on the right pane and run that line!

Note: The first time you do this you may be asked which pane vim-slime should 'send' the code to, with the numbers displayed over the panes. For example in kitty I'm usually sending to pane 2, so I press: 2 enter enter. If it was pane 5, I'd press 5 enter enter etc.

If the line of code is immediately proceeded by another line(s) it will run that/those as well (for example, a multi-line Active Record query). It will do the same if there's one or more lines immediately above the current line. This takes a tiny bit of getting used to as you may unintentionally run lines immediately above/below the line for a short while.

That's all there is to it!

A few tips

- As explained above, ctrl + c ctrl + c will run the line under the cursor. But you can also select and run any code you want by selecting it with vim's visual mode and ctrl + c ctrl + c to run that selected code. For example, if you want to run part of a line, select it in visual mode and ctrl + c ctrl + c and it will run! Same for say a few hundred lines of code: select it all in visual mode (e.g. v ctrl + f ctrl + f then j or k to get to the exact line), then ctrl + c ctrl + c will run everything you selected.

- Rails specific: The rails console has a pager set to 'on' by default (this would necessitate back and forth between panes in order to press 'q' to quit out of the pager). So I turn it off by adding one line (IRB.conf[:USE_PAGER] = false) to ~/.vimrc or just .vimrc in the project directory.

Let me know if you have any questions/troubles.

jwr · 8 months ago
That is a very interesting journey — mine was exactly opposite, after many years with Common Lisp, I moved to Clojure and wouldn't even think of going back. I find it intriguing that the author would want to move in the other direction, especially as concurrency was mentioned (one of the main reasons why I initially looked at Clojure).

I wonder what it was about babashka that didn't work for the author. When I need a quick script with batteries included, I use babashka and it works great.

djha-skin · 8 months ago
I had already written large, nontrivial apps (linked in article) which required more libraries than babashka was written with, including ones I had written but also others. I therefore needed to run native-image on my own codebase, as it was not runnable from within babashka (at the time? I don't know if it is now).

Running native-image on an already established, not-written-for-it codebase is a nightmare. I just tried again some months ago on the linked code bases. native-image wouldn't budge. Kept getting hung up on I don't even know what, the errors were way too opaque or the app just misbehaved in weird ways.

jwr · 8 months ago
Ok, that explains why babashka wasn't suitable. I still wonder, though, about the requirement to have an executable.

I still remember many years of reading comp.lang.lisp, where the #1 complaint of newcomers was that "common lisp cannot produce a native executable". I remember being somewhat amused by this, because apparently nobody expected the same thing from other languages, like, say, Python. But apparently things have changed over the years and now CL implementations can produce bundled executables while Clojure can't — how the tables have turned :-)

iLemming · 8 months ago
> I moved to Clojure and wouldn't even think of going back.

It's always amusing to watch programmers arguing for superiority of their favorite language(s) over others, often bashing language features without clearly understanding their purpose.

And it is especially amusing to watch Lispers trying to argue with each other. "I chose Scheme", "I picked Clojure", "I moved to CL"... etc.

Bruh, I move from one Lisp to another based on my current needs. It's harder for me to choose new shoes than switching between Lisp dialects. Once you learn any Lisp to a sufficient level, the mental overhead between Lisps becomes almost negligible - it feels like practically operating the same language.

Sure, each Lisp is unique and they all have different flavors, but seriously, shouldn't we celebrate the diversity and be happy that we have at least one Lisp for every platform?

@jwr This isn't meant as criticism of your comment. I'm not arguing at all with what you wrote; Clojure is my favorite Lisp flavor as well. I'm just taking a sentence out of context and using it as a cue for my rant - don't be mad, we're cool.

jwr · 8 months ago
Yes, I think this is perpendicular to my comment. I stopped arguing about language superiority a long time ago, my comments were intended to reflect my own journey only.
Naru41 · 8 months ago
More than decade ago, I didn't understand an actual value of Lisp, but I remember this song well.

https://www.youtube.com/watch?v=HM1Zb3xmvMc

crispyambulance · 8 months ago
Every programming language should have a music video!
iLemming · 8 months ago
Heh, every function in every Lisp needs its own song (:

Here's one for clojure.core/lazy-cat

https://suno.com/song/d012fa48-d5c1-46f4-8561-9a031cfb8925

Makes me sad that Clojure has mapcat and lazy-cat functions, but they've never made any effort to create mapdog and lazy-dog variants. I firmly believe that is the unique and only factor that has prevented Clojure from becoming a mainstream language at the top of the RedMonk chart.

BreakMaker9000 · 8 months ago
Wondering whether a dialect like Jank [1] may be worth a shot?

[1] https://jank-lang.org/

cylinder714 · 8 months ago
Its author is quitting his job to work on it full time: https://jank-lang.org/blog/2025-01-10-i-quit-my-job/
aidenn0 · 8 months ago
As a counterpoint to author's use of vim-slime (not to say I don't believe author's commet of "I'm Okay, I Promise," but rather to communicate to others who are facing a similar choice:

I am a lifelong vim user (since elementary school in the early '90s), and I developed common lisp using vim for over a decade. I still use vim for nearly everything, but emacs as my Lisp IDE. Before evil-mode, I used the mouse and menus for 90% of what I did, and it was still an improvement over the best vim had to offer at the time (vim-slime existed back then, but would crash or hang regularly).

Author's vim setup is fairly good, but Emacs/slime is still better. They stopped using emacs because of RSI, but their vim setup defaults to "v a ( C-c C-c" to accomplish something that is "C-c C-c" in emacs/slime. They have altered it to be "v a ( <space> g" which begs the question of "why not remap keys in emacs?"

pntripathi9417 · 8 months ago
I have been working with Clojure for 5+ years now. For CLI applications babashka has worked quite well for us.

Would love to know more about the problems you faced.

In my experience whenever I faced such issues - it has been because I am not using it well.

For CLOS kind of things I have found https://github.com/camsaul/methodical library quite well and the performance is better than default multimethods in core clojure implementation.

chii · 8 months ago
> spent long, hard hours banging my head against native-image and it just wasn't working out.

it would be nice to know what exactly isn't working out and what the problems with native-image was.

Coz i think clojure is as close to perfect, imho, as a language can go without selling out.

huahaiy · 8 months ago
Graalvm native image for Clojure is a solved problem. Just add this library to the project and add a flag to native image command line.

https://github.com/clj-easy/graal-build-time

This initializes Clojure classes at build time and it mostly works for pure Clojure code.

Doing complicated things (e.g. depending on native library, etc.) requires some tweaking. For example, a few packages may need to be declared as initialized at build time or run time, depending what they are doing. And any unresolved classes need to be added to reflection-config.json.

All these are easily discoverable if one talks to people in the Clojurian slack channels. Clojure is a small community, so it helps to be part of it, because there are not a lot of open materials on the Web.

IshKebab · 8 months ago
> solved problem

except...

> mostly works

> requires some tweaking

> discoverable if...

I know nothing about Clojure but from your caveats I think I can see why he spent hours banging his head against a wall.

djha-skin · 8 months ago
I actually just dusted off my old Clojure stuff to see if it was a "solved problem", and it isn't.

I grant that it might be described thus if I started out with that stack, but trying to retrofit an older code base with it is, I have found, next to impossible. You have to code around the myriad gotchas as you go or you're never going to identify all those landmines going back over it after the fact. The errors and bad behaviors are too difficult to identify, even for the `native-image` tooling.

m1n1 · 8 months ago
what are you referring to when you say a language can sell out?