Some random notes from using ClojureCLR (.NET Core version) on Mac OS. YMMV, obviously :)
The REPL provided by Clojure.Main
does not support niceties like history, or even using arrow keys to
move around while editing. On Linux and Mac, this may be solved by rlwrap,
which is also used to enhance the built-in REPL in JVM Clojure (included in the clj
script). To create a similar
wrapper for Clojure.Main, you can create a cljr
script (and place it somewhere on $PATH
) as follows:
#!/usr/bin/env bash
bin_dir="$HOME/.dotnet/tools/"
if type -p rlwrap >/dev/null 2>&1; then
# See https://github.com/hanslub42/rlwrap/blob/master/doc/rlwrap.man.in
# for the meaning of each flag used here
exec rlwrap \
--always-readline \
--no-children \
--remember \
--quote-characters '\"' \
--break-chars "(){}[],^%#@\";:'" \
"$bin_dir/Clojure.Main" "$@"
else
echo "Please install rlwrap for command editing or use \"Clojure.Main\" instead."
exit 1
fi
Ideally, this script would be part of the distribution for these platforms. I do not know if anything similar exists for Windows.
While the name Clojure.Main
might make sense in the context of a dotnet package, it feels rather alien as a name
for an executable, at least on Mac or Linux. I think it would be sensible to have this renamed, or at minimum symlinked,
to something like clojure-clr
for those platforms. This would also align better with the JVM Clojure binary, which is
simply named clojure
.
JVM Clojure seems to have standardized on using brew as the package manager for distribution of binaries. In order to provide a similar process regardless of target platform, it would be nice if ClojureCLR did the same, and allowed for something like:
brew install clojure-clr
To install both Clojure.Main
, the required dotnet pacakge, the
aforementioned rlwrap
package and the cljr
wrapper script.
For an example of another dotnet application installed via brew, see the gitversion formula.
About the dotnet
package — ClojureCLR, when used with .NET Core (as is what you'll get on Mac/Linux) currently
seems to require dotnet
version 6 (can be installed with the dotnet@6
package) and not the latest version 7.
Unless there are some requirements for why this must be, it'd be great if this dependency was bumped to dotnet 7,
as to not require the installation of a legacy package. There's also a chance that the user has some other software
depending on the dotnet
(7) package, and having to manage both is likely not a great experience.
To use brew to prepare for use of ClojureCLR, this is currently how it can be done:
$ brew install dotnet@6 rlwrap
$ export DOTNET_ROOT="/opt/homebrew/opt/dotnet@6/libexec" # <-- add to ~/.bashrc, ~/.zshrc ...
$ dotnet tool install --global Clojure.Main
If dotnet is previously installed, one might also need to put the dotnet@6
version first in the $PATH
,
as suggested by brew:
echo 'export PATH="/opt/homebrew/opt/dotnet@6/bin:$PATH"' >> ~/.zshrc
ClojureCLR does not seem to be built in the same GitHub environment where the source code resides. If the project was built continuously using GitHub Actions, it would make the PR process easier for contributors, as it would provide transparency in the status of builds, as well as making the publishing process integrated with the builds.
Binaries (or zip-files) are currently published to SourceForge. Using GitHub for both builds and releases would cut out an extra dependency, and would help with discoverability, as releases would be linked from the first page of the ClojureCLR project.
Having a robust way to pull in dependencies, whether from Clojars or Nuget, seems detrimental to the viability of ClojureCLR as an alternative to JVM Clojure. My experiments with the old lein-clr plugin have not been a great experience, and while I rather like Leiningen, much of the Clojure world is now using deps.edn, so it would probably make sense for ClojureCLR to provide a port of that.
Since HTTP is generally what services use to communicate, it should be high priority to have options for both HTTP client and server functionality in the form of libraries compatible with ClojureCLR. In order to minimize differences between implementations, it would likely be a good idea to port popular libraries like clj-http for a client, and ring for server implementations.
- The
using
keyword for automatic closing of anIDisposable
in dotnet translates towith-open
in ClojureCLR