Skip to content

Instantly share code, notes, and snippets.

@anderseknert
Last active January 7, 2023 09:05
Show Gist options
  • Save anderseknert/237e0d01dcbbe8ef1acb2d754e3516b6 to your computer and use it in GitHub Desktop.
Save anderseknert/237e0d01dcbbe8ef1acb2d754e3516b6 to your computer and use it in GitHub Desktop.
ClojureCLR notes

ClojureCLR Notes

Some random notes from using ClojureCLR (.NET Core version) on Mac OS. YMMV, obviously :)

REPL

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.

Releases, packaging & distribution

Clojure.Main -> clojure-clr

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.

brew

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

Builds and distribution

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.

Wish list

deps.edn

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.

HTTP libraries

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.

Random observations

  • The using keyword for automatic closing of an IDisposable in dotnet translates to with-open in ClojureCLR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment