so I’m trying to learn #clojure and would love some advice

the way that I usually write code is to define exactly what type of data each function expects, and exactly what type of data it returns. (like Python’s type annotations or Racket’s contract system) I find that very helpful for keeping track of what my functions are for, and for making sure that I’m using them correctly (this is especially helpful for quickly finding incorrect function calls after I refactor a function)

ideally I’d like to have either static analysis, or a runtime error be thrown if my functions aren’t being called correctly (or if they’re returning invalid data)

it looks like Clojure has a few different options for doing something like this:

do y’all have a recommendation for which I should use, and maybe a link to a guide on how to use it? I’m ngl the documentation that I’ve found for all of these so far intimidates me a lot lol, so I would love something simpler

GitHub - plumatic/schema: Clojure(Script) library for declarative data description and validation

Clojure(Script) library for declarative data description and validation - plumatic/schema

GitHub

@kasdeya one thing worth considering: try to keep your schema declarations separate from your function definitions. ideally your function code stays plain idiomatic Clojure, and the schemas live alongside it (or even in a separate namespace).

if your functions stay "normal," you can use standard Clojure tooling like clojure-lsp, editor's jump-to-definition, etc. — all of which just works out of the box. once you start adding schema macros into your defns, some of that tools can get confused.

@kasdeya from that angle, malli and spec are better choices than schema, since they make it more natural to define schemas independently of your functions.

that said, schema can be more powerful in certain cases — for example if you need to define schemas for protocol definitions. so it's not that schema is bad, it just takes a different approach.

@kasdeya for getting started I'd lean toward malli — it has a nice data-driven syntax that feels less intimidating than spec, and the separation between "here's my function" and "here's what it expects" stays clean.