As a side project I’m creating a Clojure DSL for image synthesis (clisk).
I’m a little unsure on the best approach to function naming where I have functions in the DSL that are analogous to functions in Clojure core, for example the + function or something similar is needed in my DSL to additively compose images / perform vector maths operations.
As far as I can see it there are a few options:
- Use the same name (
+) in my own namespace. Looks nice in DSL code but will override the clojure.core version, which may cause issues. People could get confused. - Use the same name but require it to be qualified (
my-ns/+). Avoids conflicts, but prevents people fromuseing the namespace for convenience and looks a bit ugly. - Use a different short name e.g. (
v+). Can beused easily and avoid clashes, but the name is a bit ugly and might prove hard to remember. - Use a different long name e.g. (
vector-add). Verbose but descriptive, no clashes. - Exclude
clojure.core/+and redefine with a multimethod+(as georgek suggests).
Example code might look something like:
(show (v+ [0.9 0.6 0.3]
(dot [0.2 0.2 0]
(vgradient (vseamless 1.0 plasma) ))))
What is the best/most idiomatic approach?
first, the repeated appearance of operators in an infix expression requires a nice syntax, but for a lisp, with prefix syntax, i don’t think this is as important. so it’s not such a crime to have the user type a few more characters for an explicit namespace. and clojure has very good support for namespaces and aliasing. so it’s very easy for a user to select their own short prefix:
(x/+ ...)for example.second, looking at the reader docs there are not many non-alphanumeric symbols to play with, so something like
:+is out. so there’s no “cute” solution – if you choose a prefix it’s going to have to be a letter. that means something likex+– better to let the user choose an alias, at the price of one more character, and havex/+.so i would say: ignore core, but expect the user to
(:require .... :as ...). if they love your package so much they want it to be default then they can(:use ...)and handle core explicitly. but you choosing a prefix to operators seems like a poor compromise.(and i don’t think i have seen any library that does use single letter prefixes).
one other possibility is to provide the above and also a separate package with long names instead of operators (which are simply def’ed to match the values in the original package). then if people do want to
(:use ...)but want to avoid clashes, they can use that (but really what’s the advantage of(vector-add ...)over(vector/+ ...)?)and finally i would check how
+is implemented, since if it already involves some kind of dispatch on types then georgek’s comment makes a lot of sense.(by “operator” above i just mean single-character, non-alphanumeric symbol)