Fork me on GitHub
#clojure-spec
<
2020-06-01
>
jaide01:06:51

A friend shared this with me http://gizmo385.github.io/clojure/programming/2015/08/11/adts-in-clojure.html which ended with a macro for (data Tree = Empty | Leaf value | Node left right). I'm trying to write the spec for something like that just for learning purposes. I got to (s/def ::tree (s/or empty?)) before getting a bit stuck 😅

jaide01:06:02

My first question is can you compose specs together like (def ::leaf ...) (def ::node ...) (def ::tree (s/or empty? ::leaf :;node))?

seancorfield01:06:38

I think you'd need "tagged" data structures and multi-spec for that @jayzawrotny

jaide01:06:30

Ah thanks for the pointer!

jaide02:06:31

Found from https://gist.github.com/Olical/f2b934873a49c0638ca673ab764a0131

(s/def ::element (s/or :string string?
                       :element (s/cat :name keyword?
                                       :attrs (s/? (s/map-of keyword? any?))
                                       :children (s/* ::element))))

jaide02:06:03

That's really close I think!

jaide02:06:17

(s/def ::tree (s/or :empty empty?
                    :node (s/tuple (s/? ::tree) (s/? ::tree))
                    :leaf number?))

jaide02:06:41

It's getting [] => :empty, but failing on anything else

jaide02:06:55

(ns spec-intro.core
  (:require
   [clojure.spec.alpha :as s]))


(s/def ::tree (s/or
               :empty (s/and coll? empty?)
               :node (s/cat :left (s/? ::tree)
                            :right (s/? ::tree))
               :leaf number?))

(def tree [0 [1 [2 3]]])

[(s/conform ::tree tree)
 (s/conform ::tree [1 0])
 (s/conform ::tree [])
 (s/conform ::tree 1)]

plexus14:06:57

regarding my question from yesterday re. infinite recursion in generators, I managed to work around it with size/`resize`, basically making sure that nested generators get increasingly smaller size parameters, and always emitting terminal tokens at small sizes https://github.com/lambdaisland/regal/blob/master/src/lambdaisland/regal/spec_alpha.cljc#L21-L33

👍 12
plexus14:06:52

maybe that's useful to someone 🙂