Fork me on GitHub
#clojure
<
2023-05-30
>
jaide19:05:55

Attempting to implement something akin to spec in fennel. Starting small. Was curious how the ops like s/and and s/or work under the hood. Was anticipating they would return a function that does some kind of check and returns data that functions like s/confirm and s/verify can use. However, it actually returns some kind of object I don't have much info about. Any kind of hints about how that all works?

clojure
(pprint (s/and number? int?))
#object[clojure.alpha.spec.impl$and_spec_impl$reify__1802 0x382dc417 "clojure.alpha.spec.impl$and_spec_impl$reify__1802@382dc417"]

🙌 2
p-himik19:05:38

It creates a new object that implements some required protocols. The implementation is relatively straightforward, but there's a lot under the hood to explain in plain English without copying the whole code.

jaide20:05:12

That's fair. Trying to study it on my phone while waiting for the subway was probably net the best first attempt. Will just have to take my time to grasp it 🙂

borkdude20:05:41

I don't know fennel, but maybe https://github.com/borkdude/spartan.spec comes in handy. It's an implementation of spec with just maps and functions, no protocols

jaide20:05:23

Oooh that's a big help! Thanks again

borkdude20:05:24

it was first used in bb when bb didn't have support for protocols yet

jaide20:05:59

Are protocols achievable in nbb?

borkdude20:05:11

yes, they work

jaide20:05:22

Oh my mistake

borkdude20:05:06

SCI powers both bb and nbb, so in terms of language features those are similar

jaide20:05:28

Oh right, that makes sense.

jaide20:05:06

Great, spartan was exactly what I needed. That makes more sense now and unblocks me. Thanks immensely!

👍 2
jaide03:06:50

Alright here's my book report: • A spec is essentially a specialized hash-map (enforced in clj via protocols) with... • :type ::spec, • :cform conform function that returns a value or ::invalid:explain function that communicates which predicate failed, and the path within the tree to get there • :describe function that shows the symbols that it would run • Specs are registered with unique keys against a shared registry, usually an atom • Macros like s/and transform the predicates it receives into specs themselves • Forms like s/and use macros instead of functions so it can quote the predicate forms passed into it