https://github.com/idanmel/tic-tac-clojure/ After a couple of years of trying to stick with learning Clojure, I created a tic-tac-toe "game engine". Any feedback would be appreciated. π
Instead of This is the only function that should be used from outside this namespace...
, you can use defn-
to make fns private to the namespace.
Also even though this is a pretty contained project and you don't have a lot to gain, on top of replacing most defn
s with defn-
(or instead of it) you can have a separate api
namespace just for symbols that are meant to be exposed to the world
I'd also add some specs and try to use them to validate the user's input (e.g. move
)
to find out if/how I could "reduce" the boilerplate in the turn
function
Thanks everyone, I'll make the recommended changes.
@jaihindhreddy @pavlos Coming from Python, it will not common practice to use private functions. Is it common practice to use defn- in Clojure?
@idanmel In my experience, what's more common, is for projects to have entire namespaces with impl
in their name, and no promises made to the consumer. This way might be a little cleaner. But you do tend to see defn-
too. Also, there is no enforcement as such. You can still call private fns from other namespaces (, you'll get warnings of course).
@jaihindhreddy "namespaces withΒ `impl`Β in their name" Not sure what that means, and google comes up short for me. Where can I read about it?
@idanmel For an example of this, https://github.com/tonsky/datascript/tree/master/src/datascript. The impl
folder contains namespaces that are to be considered implementation detail by consumers.
You can also put :private true
https://clojure.org/reference/metadata on namespaces too (like defn-
does to functions), but I don't think that does anything.
Thanks @jaihindhreddy, I'll look into it!
@jaihindhreddy, I implemented the impl. Thanks π
One thing I noticed is that your docstrings should be before the function parameters. Anything after the function parameters is evaluated, so each function is actually initializing the string the immediately forgetting about it
in draw-status
you can use when
instead of if
A style I prefer is to destructure right in the parameters.. i.e. instead of
(defn f [foo]
(let [{:keys [a b]} foo] ...))
you could just do:
(defn f [{:keys [a b]}] ...)