Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid name clashes in a Clojure DSL

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:

  1. 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.
  2. Use the same name but require it to be qualified (my-ns/+). Avoids conflicts, but prevents people from useing the namespace for convenience and looks a bit ugly.
  3. Use a different short name e.g. (v+). Can be used easily and avoid clashes, but the name is a bit ugly and might prove hard to remember.
  4. Use a different long name e.g. (vector-add). Verbose but descriptive, no clashes.
  5. 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?

like image 374
mikera Avatar asked Jul 23 '12 07:07

mikera


1 Answers

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 like x+ - better to let the user choose an alias, at the price of one more character, and have x/+.

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)

like image 188
andrew cooke Avatar answered Dec 10 '22 09:12

andrew cooke