Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure CLI by

Ok, regardless of editor, running clj in a directory will start a repl that has "project context" to project deps.edn in that directory, and that is the way that most Clojure developers create a connected repl.

The implication seems to be to work on a different project one must (System/exit 0) VM and start another VM using clj command to ‘create a connected repl’ to project deps.edn in a different directory? This appears to be idiomatically (colloquially) referred to as ‘restarting the REPL’ I believe?

Seems rather draconian for a dev env, let alone a lisp dev env? I thought the highly dynamic heritage of lisp replete with multiple REPLs was universally sought after? 10 years later and no multiple REPLs for clojure? Personally, I’m somewhat surprised, but maybe nobody really wants, needs or requires multiple clojure REPLs? I think multiple REPLs could be transformational in many use cases IMHO, or maybe I’m really ‘out of the loop’ no pun intended?

03-10-2015 Clojure stream socket repl discussion (https://groups.google.com/g/clojure-dev/c/Dl3Stw5iRVA/m/mgwvmEnjnBoJ) several notable sub-quotes:

“I think it is important, with tooling, to have the broadest, open notion of the types of 'use cases' for Clojure, and for workflows of people using Clojure, lest you actually limit them. I hope people are able to write their languages and DSLs, test embedded control/debug consoles, design next-generation REPLs and debuggers, grab data dumps etc, all from their REPL. That's the heritage of Lisp. Many people are doing data science, languages, genetics, rule-systems etc type things with Clojure, not just web apps

But it is quite common in rich Common Lisp IDEs like Lispworks for people to have multiple listener (REPL) sessions open at the same time (against the same runtime). You can launch long running processes that produce streaming output, switch to another listener and continue interaction and development, have separate listeners for separate contexts/state/command-history etc. There's a lot to Lisp development that's not RPC.

Note multiple listeners, data inspectors and more. Maybe not the latest GUIs, but the capabilities should be a source of inspiration for any Clojure IDE.”

Previously hinted personal end goal: exploit ‘critical mass’ for a (truly) ‘dynamic’ clojure dev env, including dynamic java recompilation, namespace reloading, etc. and include at a minimum:

  • clojure.repl.deps
  • clojure.tools.build.api (clojure.tools.build)
  • clojure.tools.deps
  • clojure.tools.deps.cli.api (clojure.deps.cli)
  • clojure.tools.namespace
  • clojure.tools.tools.api (clojure.tools.tools)
  • GitHub - clj-commons/virgil: Recompile Java code without restarting
    the REPL (https://github.com/clj-commons/virgil)
  • other polyglot ‘evaluation/compilation’ TBD

I also included a few tools to help come back up to speed quicker:

Eventually will look at many ‘current projects’ including: GitHub - HumbleUI/HumbleUI: Clojure Desktop UI framework (https://github.com/HumbleUI/HumbleUI) as stated to build better apps than possible with web, AND access full power of your computer (multithreaded), wouldn’t that be convenient?

Another quote from 03-10-2015 Clojure stream socket repl discussion (https://groups.google.com/g/clojure-dev/c/Dl3Stw5iRVA/m/IHoVWiJz5UIJ):

“REPL stands for something - Read, Eval, Print, Loop. It does not stand for - Eval RPC Server/Window.”

Anyway, that would be ERSW, seriously, I couldn’t agree more, a required lisp feature, for me anyway: multiple simultaneous-concurrent (multi-threaded) REPLs, I refer to as ‘Clojure Listeners’ (‘in-process’ or ‘against the same runtime’) non-socket non-nREPL non-LSP non-network non-middleware non-multi-VM based REPL approaches that support multiple simultaneous dev management ‘native VM’ approaches for polyglot projects ala GraalVM.

[SEE Multiple Clojure Listeners] (https://github.com/mgrisius/clj-mode/blob/0.9/Clojure_Listener_2025-02-23_09-02-41.jpg)

Note JavaScript Listener “JS-1” pictured. Could have python, R, ruby, or whatever language(s) available in GraalVM. ‘Clojure Listeners’ used with or without emacs, ‘regardless of editor’, in any Java VM for that matter. Could easily have multi-threaded socket-based listeners . . .

Clojure Listeners: multi-threaded, full history, type ahead, line editing, completion, pop-up menus, colorized output, colorized-balanced-brackets-([{, etc. Also working on other listener features: multi-line editing, enhanced source lookup, doc lookup, repo-artifact search, embeddable .e.g. in morse, etc. all leveraging the ‘purest clojure value chain possible’!

As previously mentioned, my basic ‘old style’ simple.bat with (~60mb) über jar simple compatibility with emacs lisp-inferior-mode works good with ‘legacy’ approach and new ‘CLI deps.edn approach’ basic use so far, both with ~1 second startup time. Zero optimization has been done thus far, e.g. GraalVM native image, etc.

My forward-looking goal & reason for asking initial question: compatibility with future clojure tool direction(s), NOT invent the next ‘technical debt’ ad hoc one-off hack. My Holy Graal: I want a fully dynamic long running VM under full clojure programmatic control.

So, the question remains: a) how to programmatically set REPL with ‘context’ for ‘project-1 aware’? b) how to programmatically switch REPL ‘context’ to ‘project-n aware’?

1 Answer

0 votes
by

The implication seems to be to work on a different project one must (System/exit 0) VM and start another VM using clj

You don't have to exit the existing REPL process before starting a new one. You can have however many running clj instances, all inside different or the same projects.

If you want to switch to a different project from within the same window, be it a terminal or some IDE or something else, then it might also be possible but then it depends on what that "something" is. In a terminal, people usually use screen or tmux for something like that, or even Ctrl+Z with fg or bg if you're on Linux and maybe Mac or WSL.

This appears to be idiomatically (colloquially) referred to as ‘restarting the REPL’ I believe?

If it's all in the same process - yes. Although usually it means restarting a REPL within the same project, since nothing between projects conflicts with each other.
If there's a server process for the REPL and a client process, it might mean restarting both or restarting only the server if the client can reconnect without restarting.
But usually all the fine points are not important at all.

a required lisp feature, for me anyway: multiple simultaneous-concurrent (multi-threaded) REPLs, I refer to as ‘Clojure Listeners’ (‘in-process’ or ‘against the same runtime’)

I have never experienced or even heard of a need for that, so I'm curious what the actual use case is that isn't satisfied with multiple separate REPLs.

In any case, even that is possible if you start multiple socket REPLs.

non-socket non-nREPL non-LSP non-network non-middleware non-multi-VM based REPL approaches

But why all the limitations? Do they have any purpose?

SEE Multiple Clojure Listeners

I have no idea what I'm looking at, there's very little context on that image.

Could easily have multi-threaded socket-based listeners . . .

But you said "non-socket" above?..

Clojure Listeners: multi-threaded, full history, type ahead, line editing, completion, pop-up menus, colorized output, colorized-balanced-brackets-([{, etc. Also working on other listener features: multi-line editing, enhanced source lookup, doc lookup, repo-artifact search, embeddable .e.g. in morse, etc.

You're just describing an IDE, just with that small addition of "multi-threaded REPL" with a yet-unclear-to-me value add.

I want a fully dynamic long running VM under full clojure programmatic control.

That's a very, very vague statement, specifically the "fully dynamic" part.

I'm still not entirely sure what's going on here, but I feel that it might be useful to add that at least on JVM you'll have issues in your attempts to be "fully dynamic" in case it also means "changing dependencies within the same process". There are tools to add dependencies at run time, but you cannot remove them. You cannot have two of the same things as well. And you cannot update a dependency to a version that made a breaking change and expect things to continue working exactly as they did before.

With that being said an given the sheer length of your opening message and the length of the previous message, I'm absolutely certain that such a discussion is much better to be had via some more interactive medium, like Slack or Zulip. There's much less risk of getting stuck in the weeds only because you took a wrong turn, and it's much easier for both the writer and all the readers to unfold the idea piece by piece instead of having to deal with a truck load of vague info.

...