beginners 2026-08-02

I'm currently trying to call a function numerous times, running through a 2-D vector and each time sending the function: • the content • the first index • the second index I'm thinking map-indexed might work but I haven't figured it out or figured out that this won't work and I should do the above some other way.

Can you give a sample code?

It was going to be something like: (map-indexed (map-indexed function (nth 2-d-vector _passed-in row?_)) 2-d-vector) but I didn't even know where to start to get that passed-in outer index. So then I tried for (2, nested) so many different ways but couldn't get it to work. I couldn't even get it to work for a single dimension version. Completely frustrating. So then I tried loop (2, nested) (with when and recur) and finally got that to work. I wouldn't be surprised if map-index just can't be used for my purpose, but I am very surprised for doesn't seem to work!! The working code was this. (loop [row 11] (when (> row -1) (println (str row)) (loop [column 4] (when (> column -1) (print (str column)) (js/console.log "(str row column) = " (str row column)) (function (get (get 2-d-vector row) column) row column) (recur (- column 1)) ) ) (recur (- row 1)) ) ) Could this be done with for instead?

map-indexed accepts a function and a collection. The inner map-index is correct. The outer map-index is wrong - its second argument is the result of the inner (map-indexed ...), but it should be a function that calls map-index instead.

> Could this be done with for instead? It can be, since for is very generic. But it will look much more verbose and will probably be slower than two correctly used nested map-indexed.

I'm trying to understand your map-index explanation. How can my inner expression be correct if I have my stand-in variable idea there? (passed-in outer index?) What would a working version of it all be? Also, would a for implementation at least be less verbose (and/or a better choice in some way) than my loop implementation?

Suppose you have a vector like [:a :b :c ...]. You process it, along with the indices of the items, like this: (map-indexed (fn [index element] ...) the-vector). The fn will first receive args 0 :a, then 1 :b, then 2 :c, and so on. That's what you basically already have for the inner map-indexed, you just didn't figure out how to extract the-vector. So if you have something like [[:a :b :c] [:d :e :f] ...], you'd do this:

(let [data [[:a :b :c] [:d :e :f] [:g :h :i]]]
  (->> data
       (map-indexed
         (fn [outer-idx inner-vec]
           (->> inner-vec
                (map-indexed
                  (fn [inner-idx elem]
                    {:outer-idx outer-idx
                     :inner-idx inner-idx
                     :elem      elem})))))))

By the way, I all the searching I did to try to solve this, I did come across an opinion that vector indices really shouldn't be used for anything other than accessing things, so maybe I shouldn't be having them serve as row and column numbers in the first place, and I should have a 3d vector instead, with the row and column saved that way?

for would be about as verbose. You'd still have to use map-indexed or map+`range`+`vec` to create tuples of indices+items over which you'd iterate.

> I did come across an opinion that vector indices really shouldn't be used for anything other than accessing things That's a very vague statement. Arguably "used for accessing things" does cover "row and column numbers".

> I should have a 3d vector instead, with the row and column saved that way? Sorry, no idea what you mean.

I think I'll have to have a re-read of this tomorrow. I do notice there, though, what I know to be called the threading symbol (macro?) but haven't used yet, and that seems key.

I'm not sure about the outer-idx, inner-idx, and inner-vec, though. The first two sound like the temporary variables that would be used with fors or loops and which I thought using map-indexed might be able to avoid, and the third I don't understand because the only named vector I can refer to is what I believe you are calling outer-vec, the whole 2-d vector.

->> is not key, it's just lets you reshuffle things around to somewhat easier see what's what. (->> a (b c) is equivalent to (b c a).

So your code could be done to not use threading? That might make it make more sense to me.

> I'm not sure about the outer-idx, inner-idx, and inner-vec, though [...] Alright, you seem to be in a completely different mind state, so much so I'm not even sure where the source of confusion is. map-indexed lets you use indices in addition to the elements. If you don't need indices and only need elements, then you don't need map-indexed, you can do just fine with plain map or mapv or anything similar. As you can see, I don't use the indices in map-indexed to fetch stuff, I only use them in the result. > the only named vector I can refer to is what I believe you are calling outer-vec, the whole 2-d vector You can create names at will, it's not a precious resource. (let [x [1 2 3]] ...) - bam, [1 2 3] now has a name that can be used within the body of let. (let [x (nth some-coll 7)] ...) - bam, the 8th element of some-coll now has a name. And so on. Using map or any of its siblings binds the name to the value for you, on each step of the iteration, by the means of function calling. > So your code could be done to not use threading? That might make it make more sense to me. As an exercise, try to rewrite that code yourself. :) Not all at once, one map-indexed at a time. Run the form via the REPL on each attempt and see how it makes sense. (BTW you should really have your editor configured in a way where starting a REPL is trivial and sending a specific form to a running REPL is a single shortcut away.)

Wait, are :outer-idx and :inner-idx temporary variables that I can actually call? They come with use of map-indexed? I really don't get where those come from.

Let me try a different way. What's your background? Any specific programming language you are already comfortable with?

I've used a bunch, but none as recently as CLJS or I suppose a bit of JS. Most recent before that may have been Python.

Do you remember the map function in Python?

I didn't get to that, I think.

So, would it be fair to say that you're pretty much a beginner in programming in general, not just in Clojure?

I'm trying to rewrite your code without the threading, but I don't understand why you seem to be calling the function with 2 arguments when it takes 3.

> you seem to be calling the function with 2 arguments when it takes 3 What function are you talking about exactly? Which 2 arguments do you see? Which 3 arguments should it be taking?

The function takes (2-d-vector value, row (outer index of that value), column (inner index of that value).

Ah, I didn't use your function in my examples at all.

Since I have no idea what it was supposed to be doing (maybe you meant it as a pure function that's only there to construct the result, or maybe in your mind it should somehow affect the iteration, or maybe something else), I couldn't just use it and hope for the best.

So, forget about function for now, forget about ->> - just focus on map. Do you understand what map does in Clojure?

I'm pretty sure I could run this:

(map-indexed function (nth 2-d-vec 0))
(map-indexed function (nth 2-d-vec 1))
(map-indexed function (nth 2-d-vec 2))
(map-indexed function (nth 2-d-vec 3))
.
.
.
I'm just wondering If it can be done with one call to 2 nested map-indexeds)

The function is for an effect, not a return value, by the way. It's for drawing to a canvas.

I could do an outer loop and nested map-index too. I just thought map-indexed might be usable in a way that I never need to explicitly mention any indices from either level of the 2-d vector.

Stop worrying about function and map-indexed for a moment, it just muddies the water. > The function is for an effect, not a return value Oh, then map-indexed is not suitable at all. Well, it could be used, but it's a poor fit. And, I assume, for drawing you need not only the values but also row and column indices?

> I just thought map-indexed might be usable in a way that I never need to explicitly mention any indices from either level of the 2-d vector. If you do need those indices for drawing, they have to be mentioned explicitly. You cannot use something without mentioning it at all. Well, not without usage of unhygienic macros, at least.

> for drawing you need not only the values but also row and column indices? Yes. ...but I think this would be a way of only having to mention the first layer of them explicitly: > I could do an outer loop and nested map-index

doseq would be the most proper solution if you didn't need the indices and needed only items. Since you do need the indices, I'd use reduce-kv and ignore the accumulator entirely. reduce-kv, when used on vectors, treats them as associative collections with the indices as the keys an the values as the values.

(let [data [[:a :b :c] [:d :e :f] [:g :h :i]]
      function (fn [item first-idx second-idx]
                 (println item first-idx second-idx))]
  (reduce-kv (fn [_ first-idx inner-data]
               (reduce-kv (fn [_ second-idx item]
                            (function first-idx second-idx item))
                          nil
                          inner-data))
             nil
             data))
Note that first-idx inside the definition of function and first-idx inside the fn passed to the first reduce-kv use the same name, but it's not actually necessary. The arguments here are all positional, so their names don't matter.

> reduce-kv, when used on vectors [..] indices as the keys an the values as the values. Whoa. That sounds perfect. I will looking into that and give it a try that tomorrow. Thanks!

Well, perfect except for the potential challenge of getting both layers of indices rounded up together for passing to the function.

What do you mean? Does my code above not achieve exactly that?

Looking at code now.

You create (fn ...) in particular scopes. Those scopes have access to particular names. All that access is also the same for the body of (fn ...). Such a function is called "closure", it "closes over" the values from the outer scopes. It's like a container, you just can't look inside it from the outside - you can only use its contents from within the container.

By the way, I copied and pasted that into my editor, and I just realized that until this point I had been reading fn as a call to my function, not as a keyword for defining a new (local?) function! (I only noticed that because you have "function' and 'fn', and because of the keyword colour-coding in my editor.) That definitely would have been causing some confusion on my part!

Ah, heh, right. How have you been learning Clojure so far?

I read a lot and watched a lot of videos years ago, and read some of Brave Clojure. I've done a simple HTML and CSS website in the past. I did a bit of programmatic drawing in JS a long time ago, and more recently but still years ago I did a simple text-manipulation webapp in CLJS, with the code operating on an input freeform text field and an output one.

I'd suggest spending a few hours here: https://exercism.org/tracks/clojure Most likely, you'll finish it in one go. At least, I don't remember it being long back when I tried it. It should sort out all confusions about fn and other similar things. Hard to proceed effectively where such mishaps can happen at every corner.

And Brave Clojure is still good, I'd definitely recommend finishing it.

Seems like I keep picking up CLJS for a bit every few years, but except for that text manipulation app I get sidelined by overwhelm from all the tooling (choices and things not working), but I'm determined to get further this time and I already have.

That's why picking something up that's designed for teaching you the language and sticking to it properly matters so much. All (or most of) the choices are made for you, all the code is already written. You just have to follow, exercise your brain, ensure complete understanding. If you do that, the end result will invariably be great - no more stumbling in complete darkness.

And then you can freely choose any other tooling, libraries, approaches, etc. - when you already have a solid foundation.

After starting with the CLJS Quick Start Guide (and not the Node.js part, by the way), I wanted to stick with that set-up and learn more of the programming without changing the tooling (for instance switching to Leinigen or shadow.cljs), which eliminated a lot of potential course-like material. I know changing those things might seem simple to people more experienced in CLJS (and maybe web dev in general?), but it leaves a new person even more lost trying to learn multiple things at once. I'm already trying to learn more JS at the same time. I will check out that website, though. Hopefully it won't try to get me to use yet one more new, confusing bit of tooling. I should also return to Brave Clojure and give that a try. I think I know enough now that though it is written for using Leiningen I can still make it work for my set-up.

I will also look at that reduce-kv approach tomorrow. Thanks for your help!

> I think I know enough now that though it is written for using Leiningen I can still make it work for my set-up. You should just use Leiningen while you follow that book. No reason to avoid it there.

Does it matter past the first few pages? Can't avoid it?

Wouldn't I just have to set up my directories in a certain way manually, however it does things automatically?

I don't recall. But even if it's just for a few pages, there is still no good reason to avoid it.

Haha. Fine, I guess I'll bite the bullet and pile on another new thing and see how much extra confusion it introduces. I was enjoying being past that tooling confusion for the past few days, though.

I may have even used it before, during one of my earlier times doing a bit of CLJS. I also just heard that it doesn't change much, so yes, among potential tooling changes that doesn't sound too tricky.

I have a doubt, why are Clojure error messages so cryptic and hard to read compared to Elm/Rust & Gleam ? Is it due to JVM ? Can we try fixing it by making up a mapping ? I have no idea, any answers appreciated

👀 1

Quoting Sean: > some of the more obtuse Clojure errors are from Java stuff deep in the implementation, where Clojure's approach -- for performance reasons -- is just to "try something" and let it throw on failure (`ClassCastException` being one of the worst offenders). You might also want to try https://github.com/seancorfield/rephrase.

🙏 1

I'll also add that they're cryptic up to a point. Then you read them more or less fluently and can easily pinpoint what's wrong and where.

1
☝️ 1

I like the "this isn't going to work" markers that good linters provide in the editor nowadays.

There is an interesting essay about the quest for humane error messages (from the compiler) in #C03SRH97FDK https://jank-lang.org/blog/2025-03-28-error-reporting/

the core team (but rich specifically) don't care about error messages. there have been a number of tickets with useful patches over the years that haven't been accepted because they don't think it's worthwhile to improve the baseline messages, and they don't like writing function-specific errors ("clojure is optimized for correct programs")

spec was built into clojure's macro-expansion to improve errors but it still has the "fan out" problem where a single mistake will print 2-10 different spec issues because it doesn't know which branch of the spec you meant to target

rephrase is the best attempt at a library to improve them that i've seen, but it still has the issue of "doesn't name the specific function that failed"

granted that it's been awhile since I've regularly written clojure, but what I recall working for me as a general heuristic is "look at the middle of the stack trace". In my experience that is where the failure point is often found, sometimes nested between a bunch of references to invoke and invokeStatic

> it still has the issue of "doesn't name the specific function that failed" Yup, because that information isn't available easily in the exception (sometimes it can be derived from the stacktrace, but knowing that, say, assoc failed deep inside some stack of fn calls isn't always helpful when your code calls something else in core).

Noah's characterization is a little unfair, IMO: a major reason why the core team don't want to "improve" the error messages is that doing so would require adding specific type/shape checks to code, or adding try/catch to rethrow with a better message, and everyone would pay the performance penalty for that. They are talking about possibly having a "development" mode that runs more slowly but performs more checks but I don't know where on the roadmap/timeline something like that might drop—it feels like a lot of work and a pretty long term goal.

👎 1

Borkent has demonstrated with Clj-Kondo that it's possible to overlay pretty amazing static analysis without coupling it to the compiler. As for the category of programming mishaps that could not possibly be anticipated by static analysis, Clojure's messages don't hold anything back. That is, they do not impose any limit on what someone might do to relate the call stack to the programmer's possible intentions. Sounds like a super job for a chatbot. So, in the end, it boils down to the Clojure custodians' reluctance to put time into a gaggle of half-measures in the compiler. The way is clear for anyone at all to solve the problem fully. 🙂

Why can't they have good errors without impacting performance the way Elm/Rust/Gleam do ?

Compile errors don't impact runtime performance. Clojure has very few compile errors—most are runtime. Projects like rephrase, and the various others that inspired it, show that tooling can improve top-level exceptions at development/REPL time, but there are still limitations around the information available to such tooling.

Many of the "problematic" error messages are from Java exceptions at runtime—Clojure just lets them bubble up.

that's not true, sean. errors like deref'ing a non-atom/non-future lead to a ClassCastException, because deref-future casts the object to a future. if deref was changed from an if to a cond with a final (throw (illegalArgument "wrong type")), both deref and future would act the same way with no performance loss and all errors would be improved

i put up a patch to exactly match the existing behavior of nth but with improved error messages and i've been told that while it's not directly rejected, there's likely no path forward on merging it

You're generalizing from that one specific issue tho'...

there are many viable ways to improve error messages across the board but they require a willingness to put in the effort to improve them

Most cases don't have an existing condition to hang an error from: you'd have to add conditional code and instance? checks.

debatable. either way, the core team has decided that putting in further effort into improving error messages is not worth the effort or focus, so they don't. they used to include "error messages" as one option for "needs improvement" section in the yearly survey but have stopped because it was the top of the list every year lol

AFAICT, the whole improvements section has disappeared, so the error messages option didn't really get a special treatment.

👍 1

I feel there's some truth to that it's not a priority. I don't think the trade off being made is just performance. I think it's partially for the simplicity of the implementation, and that errors in a way become a contract surface and committing to a particular error means maintaining that contract. That and performance, I think it makes the core team hesitant to really do anything about it.

👍🏻 1

I am trying to send a working copy of my in-progress webapp to someone else, but to my surprise sending this alone doesn't work:

folder/
├─ index.html
├─ style.css
└─ out/
   └─ main.js
style.css and out/main.js are the only files referred to in index.html What else do I need? EDIT: The is from a program I have only ever built/compiled with a clj command not including --optimizations advanced, so I'll try running with that. Is that (or that or --optimizations simple) absolutely required?

If you are doing a dev build, then you need to include the source files that are used by Google Closure

If you do advanced optimizations it produces a single standalone JS file

the source files that are used by Google Closure
Does that mean all the many .js files and directories in /out/goog/?

OK, I've done a compile with advanced optimizations, and I've copied index.html style.css /out/main.js (this new, larger one) into a new folder and pointed a browser at index.html ...but no code is run.

What does it say in the console?

Loading failed for the <script> with source "file:///out/main.js". index.html:18:30

That seems like a problem with the server's root directory

I'm just pointing a browser at some folder on my hard drive, and folder that contains:

folder/
├─ index.html
├─ style.css
└─ out/
   └─ main.js

Yeah but if your script is referenced by "/out/main.js" whatever web server youre using might think that's at the root of your whole filesystem

Try a relative path

Sorry didn't completely process your message, if you are just accessing the file through the browser directly then an absolute path certainly won't work

I looked up how to have your HTML file reference to a JS file take the path as relative, and what I found was that the form I am using (and that is used in the CLJS Quick Start guide) is relative:

<script src="/out/main.js"> type="text/javascript"></script>

I haven't read that document but what I assume that means by relative is relative to the document root of a web server, that's a standard idea in web development that it may be taking for granted the reader knows about

Yes that all makes sense. Relative should be the default so things are portable. I'm fairly certain I just moved that little 3-file, 1-subdirectory structure around and had things work just fine with another little webapp in the past. I can't see any reason why it wouldn't work here. The only difference I can think of is that I was on Windows at the time and now I am on Linux.

I would suggest using a web server such as the one provided by python to serve your directory and then everything should work

Browsers have very little access to the filesystem for security reasons so accessing the file directory with file:///home/you/index.html will not have access to things relatively

Using a web server is not something I know how to do. Even less so for the person I am sending the files to. I'm really looking for a simpler solution. I did just look up the browser security situation and that seems plausible, but then why would the error message be that it can't load main.js rather than that it won't?

But if your script tag says src=./out/main.js then that should work without a web server

Fair enough, portability will always be an issue, but using a relative path such as the one I just posted should be your best bet. If it has a / at the beginning then that's understood by the system as being absolute

https://httpd.apache.org/docs/2.4/mod/core.html#documentroot this is a reference for the concept I am talking about

It's worth understanding even if you don't use a server

As for can't versus won't load, I cannot speak to the design choices of browser developers

I just took moved my main.js file out of the /out/ subdirectory and changed my HTML reference from

<script src="/out/main.js"> type="text/javascript"></script>
to
<script src="main.js"> type="text/javascript"></script>
and now it works. Given how easy it was to circumvent, I seriously doubt this was a browser security issue. Maybe it was just that I had "/out/main.js" instead of "out/main.js" (though this has not been an issue throughout the development so far) and has something to do with the Linux-specific reference to "/" as root.

Yeah like I said, / is going to be interpreted absolutely by your OS

It's confusing

But it's just the way it works

That would explain why I would have had no problem doing this years ago on Windows. Silly Linux. Using a tilda as a special symbol for the user's home folder is fine, but using a slash as a special symbol for the root folder is not smart because slash already has a meaning: every division between directories and subdirectories! There should really just be an actual, dedicated special symbol for that.

The tilde is a shorthand that in many contexts (though far from every one) is expanded into /home/you, but the / is just what it is, it is not a shorthand and it isn't expanded

It's the mount point of your filesystem, which you can see with lsblk

Yes, but even in the expansion you mentioned, the first character could be something other than "/". Root could just as well be

^
or
&
And user1's home folder could just as well be
^/home/user1
or
&/home/user1

Web development is absolutely chock full of really painful surprises

OK, I just tested this > Maybe it was just that I had "/out/main.js" instead of "out/main.js" (though this has not been an issue throughout the development so far) and that change works too, just removing the leading "/" from the path to the JS file. To many people, /directory/file.ext is the same thing as directory/file.ext And again, why has it not been tripping on this during my normal development? It was working just fine with the leading "/" there until just now when trying to extract something to send to someone.

Idk what your development setup is but when you were building this app, did you use any kind of file watcher or development server

Which you then stopped using to examine the output?

I've just started with the CLJS Quick Start Guide and added code to the CLJS file from there (and added a CSS file and tweaked the HTML file a bit). https://clojurescript.org/guides/quick-start

From glancing at that, it looks like it does provide a built-in server, that's what would be running at localhost:9000

But if you stopped the build to produce a bundle, and then tried accessing the file directly, then the behavior will be different

Does it make sense that the leading "/" would be interpreted as meaning the system root folder only for the case where the browser is reading from the file system and not the case where it is reading from a web server? I just wrote the above as a way to say it certainly doesn't make sense to me, but actually I can kind of see that being possible now. If the browser is looking at a web server then I guess it discounts looking at the system root folder, or maybe it just always takes "/" to mean the root folder of whatever file system it is looking at, which on a web server would actually be where index.html is sitting. The only thing that doesn't make sense is why this would never be an issue in a browser on Windows, but that could be because (a) browsers are just coded differently for different OSs (and Windows browers don't have to deal with that "/" = top-level directory unfortunate silliness) or (b) I may just have not had the leading "/" when I did all this on Windows years ago.

I can't tell you anything about windows but essentially what you've said is the right analysis of the situation. If you read those apache docs I linked earlier it will give you a better explanation

Yeah, you're on the right track, a /some/file.js in your html file would mean the root of the file system, or the directory where the web server is configured to serve files from, which in the file system could be something like /home/username/htdocs, /var/www/my-awesome-site.com/public or whatever, and on your local machine, the absolute path in your local file system. Best practice is to keep file paths relative for portability

As to why / is considered the file system root, that would predate Windows and DOS by a decade or two, coming from Unix (and conceptually Multics), so every now and then you'll meet people who have built on that assumption simple_smile

Related to running clj, I'm pretty sure -c is the same thing as --compile, but I can't find a reference that actually shows all of the clj options. The output from clj --help is lacking that basic info, and so are the websites it refers to "For more info", https://clojure.org/guides/deps_and_cli and https://clojure.org/reference/repl_and_main, as well as another resource I would expect to cover that basic ground, https://clojure.org/reference/clojure_cli. What gives?

--compile is a cljs.main option (not a clj option).

You can get cljs.main's help like this:

> clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.12.145"}}}' -M -m cljs.main -h
Usage: java -cp cljs.jar cljs.main [init-opt*] [main-opt] [arg*]

With no options or args, runs an interactive Read-Eval-Print Loop

init options:
  -co, --compile-opts edn     Options to configure the build, can be an EDN
                              string or system-dependent path-separated list of
                              EDN files / classpath resources. Options will be
                              merged left to right.
   -d, --output-dir path      Set the output directory to use. If supplied,
                              cljsc_opts.edn in that directory will be used to
                              set ClojureScript compiler options
  -re, --repl-env env         The REPL environment to use. Built-in supported
                              values: node, browser. Defaults to browser. If
                              given a non-single-segment namespace, will use
                              the repl-env fn found there.
  -ro, --repl-opts edn        Options to configure the repl-env, can be an EDN
                              string or system-dependent path-separated list of
                              EDN files / classpath resources. Options will be
                              merged left to right.
... lots more ...

Ohh. Thank you. Filing that command away in my notes! (and the command with clj instead of clojure, since I see those are interchangeable somehow)

clj = rlwrap clojure which provides input history in the REPL.

I remember downloading and installing rlwrap as one of the main magical incantations I invoked when following guides to get started with CLJS, but I don't understand what it does.

I was about to test what I think you mean, by running the basic CLJS RELP with clj, entering a couple of expressions, exiting, and doing that all again with clojure, then exiting and going into each and seeing what expression history I could see from each. ...but I've run into a new problem: I suddenly can't evaluate any expressions in the REPL! This is using the same command that worked in the past: JAVA_CMD=~/Documents/programming/JDKs/jdk-26.0.2/bin/java clj -M --main cljs.main --repl

The only change I could think of between when that worked an now is that I compiled my webapp in progress with advanced optimizations, so I tried compiling it without those and...now it works. Lesson learned: *Compiling with advanced optimizations _breaks the REPL*(!!)_, and compiling without advanced optimi_, and compiling without advanced optimizations is required to get the REPL working (from that program folder) again._zations is required to get the REPL working (from that program folder) again. Very surprising, but it's nice to have been able to fix something on my own. Haha.

This is why I stick to Clojure and backend work: the frontend tooling is so quirky to me.

Just my luck I'm drawn to the quirkiest thing. I just love the idea of eventually being able to make things for web+desktop+mobile.

OK, I ran my test, and it did what I thought it would. Using clojure instead of clj means losing the use of the up and down arrow keys to get old expressions. So clj is really just clojure with that history function added? OK, great.

Yup, clj is quite literally this:

> cat `which clj`
#!/usr/bin/env bash

bin_dir=/path/to/wherever/you/installed/clojure/bin

if type -p rlwrap >/dev/null 2>&1; then
  exec rlwrap -m -r -q '\"' -b "(){}[],^%#@\";:'" "$bin_dir/clojure" "$@"
else
  echo "Please install rlwrap for command editing or use \"clojure\" instead."
  exit 1
fi

rlwrap provides history for the input of any program.