Back

index (clj)

(source)

function

(index xrel ks)
Returns a map of the distinct values of ks in the xrel mapped to a set of the maps in xrel with the corresponding values of ks.

Examples

clojure
(ns clojure.test-clojure.protocols
  (:use clojure.test clojure.test-clojure.protocols.examples)
  (:require [clojure.test-clojure.protocols.more-examples :as other]
            [clojure.set :as set]
            clojure.test-helper)
  (:import [clojure.test_clojure.protocols.examples ExampleInterface]))

(deftest reify-test
  (testing "of an interface"
    (let [s :foo
          r (reify
             java.util.List
             (contains [_ o] (= s o)))]
      (testing "implemented methods"
        (is (true? (.contains r :foo)))
        (is (false? (.contains r :bar))))
      (testing "unimplemented methods"
        (is (thrown? AbstractMethodError (.add r :baz))))))
  (testing "of two interfaces"
    (let [r (reify
             java.util.List
             (contains [_ o] (= :foo o))
             java.util.Collection
             (isEmpty [_] false))]
      (is (true? (.contains r :foo)))
      (is (false? (.contains r :bar)))
      (is (false? (.isEmpty r)))))
  (testing "you can't define a method twice"
    (is (thrown? Exception
         (eval '(reify
                 java.util.List
                 (size [_] 10)
                 java.util.Collection
                 (size [_] 20))))))
  (testing "you can't define a method not on an interface/protocol/j.l.Object"
    (is (thrown? Exception
         (eval '(reify java.util.List (foo [_]))))))
  (testing "of a protocol"
    (let [r (reify
             ExampleProtocol
             (bar [this o] o)
             (baz [this] 1)
             (baz [this o] 2))]
      (is (= :foo (.bar r :foo)))
      (is (= 1 (.baz r)))
      (is (= 2 (.baz r nil)))))
  (testing "destructuring in method def"
    (let [r (reify
             ExampleProtocol
             (bar [this [_ _ item]] item))]
      (is (= :c (.bar r [:a :b :c])))))
  (testing "methods can recur"
    (let [r (reify
             java.util.List
             (get [_ index]
                  (if (zero? index)
                    :done
                    (recur (dec index)))))]
      (is (= :done (.get r 0)))
      (is (= :done (.get r 1)))))
  (testing "disambiguating with type hints"
    (testing "you must hint an overloaded method"
      (is (thrown? Exception
            (eval '(reify clojure.test_clojure.protocols.examples.ExampleInterface (hinted [_ o]))))))
    (testing "hinting"
      (let [r (reify
               ExampleInterface
               (hinted [_ ^int i] (inc i))
               (hinted [_ ^String s] (str s s)))]
        (is (= 2 (.hinted r 1)))
        (is (= "xoxo" (.hinted r "xo")))))))
clojure
(ns clojure.test-clojure.metadata
  (:use clojure.test
        [clojure.test-helper :only (eval-in-temp-ns)])
  (:require [clojure.set :as set]))

(deftest interaction-of-def-with-metadata
  (testing "initial def sets metadata"
    (let [v (eval-in-temp-ns
             (def ^{:a 1} foo 0)
             #'foo)]
      (is (= 1 (-> v meta :a)))))
  (testing "const vars preserve metadata"
    (let [[v1 v2] (eval-in-temp-ns
                   (def ^:const foo ^:foo [])
                   (def ^:const bar ^:foo [:bar])
                   [(meta foo) (meta bar)])]
      (is (= {:foo true} v1))
      (is (= {:foo true} v2))))
  #_(testing "subsequent declare doesn't overwrite metadata"
    (let [v (eval-in-temp-ns
             (def ^{:b 2} bar 0)
             (declare bar)
             #'bar)]
      (is (= 2 (-> v meta :b))))
    (testing "when compiled"
      (let [v (eval-in-temp-ns
               (def ^{:c 3} bar 0)
               (defn declare-bar []
                 (declare bar))
               (declare-bar)
               #'bar)]
        (is (= 3 (-> v meta :c))))))
  (testing "subsequent def with init-expr *does* overwrite metadata"
    (let [v (eval-in-temp-ns
             (def ^{:d 4} quux 0)
             (def quux 1)
             #'quux)]
      (is (nil? (-> v meta :d))))
    (testing "when compiled"
      (let [v (eval-in-temp-ns
               (def ^{:e 5} quux 0)
               (defn def-quux []
                 (def quux 1))
               (def-quux)
               #'quux)]
        (is (nil? (-> v meta :e))))))
  (testing "IllegalArgumentException should not be thrown"
    (testing "when defining var whose value is calculated with a primitive fn."
      (testing "This case fails without a fix for CLJ-852"
        (is (eval-in-temp-ns
             (defn foo ^long [^long x] x)
             (def x (inc (foo 10))))))
      (testing "This case should pass even without a fix for CLJ-852"
        (is (eval-in-temp-ns
             (defn foo ^long [^long x] x)
             (def x (foo (inc 10)))))))))
 
 (deftest fns-preserve-metadata-on-maps
   (let [xm {:a 1 :b -7}
         x (with-meta {:foo 1 :bar 2} xm)
         ym {:c "foo"}
         y (with-meta {:baz 4 :guh x} ym)]
 
     (is (= xm (meta (:guh y))))
     (is (= xm (meta (reduce #(assoc %1 %2 (inc %2)) x (range 1000)))))
     (is (= xm (meta (-> x (dissoc :foo) (dissoc :bar)))))
     (let [z (assoc-in y [:guh :la] 18)]
       (is (= ym (meta z)))
       (is (= xm (meta (:guh z)))))
     (let [z (update-in y [:guh :bar] inc)]
       (is (= ym (meta z)))
       (is (= xm (meta (:guh z)))))
     (is (= xm (meta (get-in y [:guh]))))
     (is (= xm (meta (into x y))))
     (is (= ym (meta (into y x))))
     
     (is (= xm (meta (merge x y))))
     (is (= ym (meta (merge y x))))
     (is (= xm (meta (merge-with + x y))))
     (is (= ym (meta (merge-with + y x))))
 
     (is (= xm (meta (select-keys x [:bar]))))
     (is (= xm (meta (set/rename-keys x {:foo :new-foo}))))
 
     ;; replace returns a seq when given a set.  Can seqs have
     ;; metadata?
     
     ;; TBD: rseq, subseq, and rsubseq returns seqs.  If it is even
     ;; possible to put metadata on a seq, does it make sense that the
     ;; seqs returned by these functions should have the same metadata
     ;; as the sorted collection on which they are called?
     ))
 
 (deftest fns-preserve-metadata-on-vectors
   (let [xm {:a 1 :b -7}
         x (with-meta [1 2 3] xm)
         ym {:c "foo"}
         y (with-meta [4 x 6] ym)]
 
     (is (= xm (meta (y 1))))
     (is (= xm (meta (assoc x 1 "one"))))
     (is (= xm (meta (reduce #(conj %1 %2) x (range 1000)))))
     (is (= xm (meta (pop (pop (pop x))))))
     (let [z (assoc-in y [1 2] 18)]
       (is (= ym (meta z)))
       (is (= xm (meta (z 1)))))
     (let [z (update-in y [1 2] inc)]
       (is (= ym (meta z)))
       (is (= xm (meta (z 1)))))
     (is (= xm (meta (get-in y [1]))))
     (is (= xm (meta (into x y))))
     (is (= ym (meta (into y x))))
 
     (is (= xm (meta (replace {2 "two"} x))))
     (is (= [1 "two" 3] (replace {2 "two"} x)))
 
     ;; TBD: Currently subvec drops metadata.  Should it preserve it?
     ;;(is (= xm (meta (subvec x 2 3))))
 
     ;; TBD: rseq returns a seq.  If it is even possible to put
     ;; metadata on a seq, does it make sense that the seqs returned by
     ;; these functions should have the same metadata as the sorted
     ;; collection on which they are called?
     ))
 
 (deftest fns-preserve-metadata-on-sets
   ;; TBD: Do tests independently for set, hash-set, and sorted-set,
   ;; perhaps with a loop here.
   (let [xm {:a 1 :b -7}
         x (with-meta #{1 2 3} xm)
         ym {:c "foo"}
         y (with-meta #{4 x 6} ym)]
 
     (is (= xm (meta (y #{3 2 1}))))
     (is (= xm (meta (reduce #(conj %1 %2) x (range 1000)))))
     (is (= xm (meta (-> x (disj 1) (disj 2) (disj 3)))))
     (is (= xm (meta (into x y))))
     (is (= ym (meta (into y x))))
 
     (is (= xm (meta (set/select even? x))))
     (let [cow1m {:what "betsy cow"}
           cow1 (with-meta {:name "betsy" :id 33} cow1m)
           cow2m {:what "panda cow"}
           cow2 (with-meta {:name "panda" :id 34} cow2m)
           cowsm {:what "all the cows"}
           cows (with-meta #{cow1 cow2} cowsm)
           cow-names (set/project cows [:name])
           renamed (set/rename cows {:id :number})]
       (is (= cowsm (meta cow-names)))
       (is (= cow1m (meta (first (filter #(= "betsy" (:name %)) cow-names)))))
       (is (= cow2m (meta (first (filter #(= "panda" (:name %)) cow-names)))))
       (is (= cowsm (meta renamed)))
       (is (= cow1m (meta (first (filter #(= "betsy" (:name %)) renamed)))))
       (is (= cow2m (meta (first (filter #(= "panda" (:name %)) renamed))))))
 
     ;; replace returns a seq when given a set.  Can seqs have
     ;; metadata?
 
     ;; union: Currently returns the metadata of the largest input set.
     ;; This is an artifact of union's current implementation.  I doubt
     ;; any explicit design decision was made to do so.  Like join,
     ;; there doesn't seem to be much reason to prefer the metadata of
     ;; one input set over another, if at least two input sets are
     ;; given, but perhaps defining it to always return a set with the
     ;; metadata of the first input set would be reasonable?
 
     ;; intersection: Returns metadata of the smallest input set.
     ;; Otherwise similar to union.
 
     ;; difference: Seems to always return a set with metadata of first
     ;; input set.  Seems reasonable.  Not sure we want to add a test
     ;; for it, if it is an accident of the current implementation.
 
     ;; join, index, map-invert: Currently always returns a value with
     ;; no metadata.  This seems reasonable.
     ))
clojure

(ns clojure.test-clojure.clojure-set
  (:use clojure.test)
  (:require [clojure.set :as set]))

(deftest test-index
  (are [x y] (= x y)
    (set/index  #{{:c 2} {:b 1} {:a 1 :b 2}} [:b]) {{:b 2} #{{:a 1 :b 2}}, {:b 1} #{{:b 1}} {} #{{:c 2}}}
  ))
noprompt/meander
(ns ^:no-doc meander.matrix.specs.epsilon
  "Operators for pattern matrices."
  (:require [clojure.spec.alpha :as s]
            [clojure.set :as set]
            [clojure.spec.gen.alpha :as s.gen]
            [meander.syntax.specs.epsilon]))

(s/fdef meander.matrix.epsilon/nth-column
  :args (s/alt :a2 (s/cat :matrix :meander.matrix.epsilon/matrix
                          :index nat-int?)
               :a3 (s/cat :matrix :meander.matrix.epsilon/matrix
                          :index nat-int?
                          :not-found any?))
  :ret (s/coll-of :meander.syntax.epsilon/node))

(s/fdef meander.matrix.epsilon/any-column?
  :args (s/cat :matrix :meander.matrix.epsilon/matrix
               :index nat-int?)
  :ret boolean?)
borkdude/speculative
(ns speculative.set
  (:require [clojure.set :as set]
            [clojure.spec.alpha :as s]
            [speculative.specs :as ss]))

(s/fdef set/index
  :args (s/cat :xrel ::rel*
               :ks ::ss/sequential)
  :ret ::ss/map)
marick/suchwow
(ns such.f-relational
  (:require [such.versions :refer [when>=1-7]]
            [such.relational :as subject]
            [such.metadata :as meta]
            [clojure.set :as set]
            [clojure.pprint :refer [pprint]]
            [midje.sweet :refer :all]))

(fact "confirm that clojure.set imports are really here"
  (fact index
    (subject/index [{:a 1}] [:a]) => { {:a 1} #{ {:a 1} }}

    (subject/index [ {:a 1} {:b 1} {:a 1, :b 1} {:c 1}] [:a :b])
    =>  {  {:a 1, :b 1}    #{ {:a 1 :b 1} }
           {:a 1      }    #{ {:a 1} }
           {      :b 1}    #{ {:b 1} }
           {          }    #{ {:c 1} }})


;;;;; The two one-level indexes

(fact "one-to-one indices"
  (let [data [{:id 1 :rest ..rest1..} {:id 2 :rest ..rest2..}]
        index (subject/one-to-one-index-on data :id)]
    (subject/index-select 1 :using index) => {:id 1 :rest ..rest1..})

  (fact "one-to-one indices where the keys are compound"
    (let [data [{:id 1 :pk 1 :rest ..rest11..}
                {:id 1 :pk 2 :rest ..rest12..}
                {:id 2 :pk 2 :rest ..rest22..}]
          index (subject/one-to-one-index-on data [:id :pk])]
      (subject/index-select [1 1] :using index) => (first data)
      (subject/index-select [1 2] :using index) => (second data)))

  (fact "options used when selecting"
    (let [data [{:id 1 :rest ..rest1..} {:id 2 :rest ..rest2..}]
          index (subject/one-to-one-index-on data :id)]
      (fact "can limit the number of keys returned"
        (subject/index-select 1 :using index :keys [:rest]) => {:rest ..rest1..})
      (fact "can add a prefix to keys as keyword..."
        (subject/index-select 1 :using index :prefix :pre-) => {:pre-id 1 :pre-rest ..rest1..})
      (fact "both"
        (subject/index-select 1 :using index :keys [:rest] :prefix :pre-) => {:pre-rest ..rest1..})

      (fact "options can also be provided as maps"
        (subject/index-select 1 {:using index :keys [:rest]}) => {:rest ..rest1..}))))


(fact "one-to-many indices"
  (let [data [{:id 1 :rest ..rest11..}
              {:id 1 :rest ..rest12..}
              {:id 2 :rest ..rest22..}]
        index (subject/one-to-many-index-on data :id)]
    (subject/index-select 1 :using index) => (just (first data) (second data) :in-any-order))

  (fact "options for one-to-many-maps"
    (let [data [{:id 1 "rest" ..rest11..}
                {:id 1 "rest" ..rest12..}
                {:id 2 "rest" ..rest22..}]
          index (subject/one-to-many-index-on data :id)]
      (subject/index-select 1 :using index :keys ["rest"]) => (just {"rest" ..rest11..}
                                                                    {"rest" ..rest12..}
                                                                    :in-any-order)
      (subject/index-select 1 :using index :keys ["rest"] :prefix "XX")
      => (just {"XXrest" ..rest11..}
               {"XXrest" ..rest12..}
               :in-any-order))))

;;; A third type of index: The Combined Index

      one-to-one-top-index (subject/one-to-one-index-on one-to-one-top :id)
      one-to-one-middle-index (subject/one-to-one-index-on one-to-one-middle :id)
      one-to-one-bottom-index (subject/one-to-one-index-on one-to-one-bottom :id)

      one-to-many-top-index (subject/one-to-many-index-on one-to-many-top :id)
      one-to-many-middle-index (subject/one-to-many-index-on one-to-many-middle :id)
      one-to-many-bottom-index (subject/one-to-many-index-on one-to-many-bottom :id)]

  (fact "selecting along a path (a building block)"
    (fact "1-N 1-N 1-N"
      (#'subject/select-along-path "top" one-to-many-top-index
                                   :foreign one-to-many-middle-index
                                   :foreign one-to-many-bottom-index)
      => (just {:id "bottom" :tag 1} {:id "bottom" :tag 2}
               {:id "bottom2" :tag 3} {:id "bottom2" :tag 4} :in-any-order))


    (fact "1-N 1-1 1-N"
      (#'subject/select-along-path "top" one-to-many-top-index
                                   :foreign one-to-one-middle-index
                                   :foreign one-to-many-bottom-index)
      => (just {:id "bottom" :tag 1} {:id "bottom" :tag 2}
               {:id "bottom2" :tag 3} {:id "bottom2" :tag 4} :in-any-order))


    (fact "1-N 1-1 1-1"
      (#'subject/select-along-path "top" one-to-many-top-index
                                   :foreign one-to-one-middle-index
                                   :foreign one-to-one-bottom-index)
      => (just {:id "bottom"} {:id "bottom2"} :in-any-order))

    (fact "1-1 1-N 1-1"
      (#'subject/select-along-path "top" one-to-one-top-index
                                   :foreign one-to-many-middle-index
                                   :foreign one-to-one-bottom-index)
      => (just {:id "bottom"} {:id "bottom2"} :in-any-order))

    (fact "1-1 1-1 1-N"
      (#'subject/select-along-path "top" one-to-one-top-index
                                   :foreign one-to-one-middle-index
                                   :foreign one-to-many-bottom-index)
      => (just {:id "bottom" :tag 1} {:id "bottom" :tag 2} :in-any-order))


    (fact "1-1 1-1 1-1"
      ;; Note that it does *not* remove the singleton wrapper around the return value.
      (#'subject/select-along-path "top" one-to-one-top-index
                                   :foreign one-to-one-middle-index
                                   :foreign one-to-one-bottom-index)
      => (just {:id "bottom"})))


    (fact "making an index and then selecting"
      (fact "1-N 1-N 1-N"
        (let [combined-index (subject/combined-index-on one-to-many-top-index
                                                        :foreign one-to-many-middle-index
                                                        :foreign one-to-many-bottom-index)]
          (subject/index-select "top" :using combined-index)
          => (just {:id "bottom" :tag 1} {:id "bottom" :tag 2}
                   {:id "bottom2" :tag 3} {:id "bottom2" :tag 4} :in-any-order)))

      (fact "1-N 1-1 1-N"
        (let [combined-index (subject/combined-index-on one-to-many-top-index
                                                        :foreign one-to-one-middle-index
                                                        :foreign one-to-many-bottom-index)]
          (subject/index-select "top" :using combined-index)
          => (just {:id "bottom" :tag 1} {:id "bottom" :tag 2}
                   {:id "bottom2" :tag 3} {:id "bottom2" :tag 4} :in-any-order)))

      (fact "1-N 1-1 1-1"
        (let [combined-index (subject/combined-index-on one-to-many-top-index
                                                        :foreign one-to-one-middle-index
                                                        :foreign one-to-one-bottom-index)]
          (subject/index-select "top" :using combined-index)
          => (just {:id "bottom"} {:id "bottom2"} :in-any-order)))

      (fact "1-1 1-N 1-1"
        (let [combined-index (subject/combined-index-on one-to-one-top-index
                                                        :foreign one-to-many-middle-index
                                                        :foreign one-to-one-bottom-index)]
          (subject/index-select "top" :using combined-index)
          => (just {:id "bottom"} {:id "bottom2"} :in-any-order)))

      (fact "1-1 1-1 1-N"
        (let [combined-index (subject/combined-index-on one-to-one-top-index
                                                        :foreign one-to-one-middle-index
                                                        :foreign one-to-many-bottom-index)]
          (subject/index-select "top" :using combined-index)
          => (just {:id "bottom" :tag 1} {:id "bottom" :tag 2} :in-any-order)))


      (fact "1-1 1-1 1-1"
        (let [combined-index (subject/combined-index-on one-to-one-top-index
                                                        :foreign one-to-one-middle-index
                                                        :foreign one-to-one-bottom-index)]
          (subject/index-select "top" :using combined-index)
          => {:id "bottom"})))


            index:person-by-id (subject/one-to-one-index-on people :id)
            index:rulership-by-person-id (subject/one-to-many-index-on rulerships :person_id)
            index:country-by-country-code (subject/one-to-one-index-on countries :country_code)


            index:countries-by-person-id (subject/combined-index-on index:rulership-by-person-id
                                                                    :country_code
                                                                    index:country-by-country-code)]

        (subject/index-select 1 :using index:countries-by-person-id :keys [:gdp])
        => [{:gdp 1690}]
        (subject/index-select 2 :using index:countries-by-person-id :keys [:gdp])
        => (just {:gdp 1690} {:gdp 513} :in-any-order)
        (subject/index-select 0 :using index:countries-by-person-id :keys [:gdp])
        => empty?

        ;; Use with `extend-map` (fully tested elsewhere)
        (-> (subject/index-select 2 :using index:person-by-id :keys [:name :id])
            (subject/extend-map :using index:countries-by-person-id
                                :via :id
                                :keys [:country_code :gdp]
                                :into :countries))
        => (just {:name "twosie" :id 2,
                  :countries (just {:country_code "NOR" :gdp 513}
                                   {:country_code "ESP" :gdp 1690}
                                   :in-any-order)}))))

(fact "one-to-one tables"
  (let [original-map {:id 1 :foreign_id "a" :rest ..rest1..}
        foreign-table [{:id "a" :val "fa"} {:id "b" :val "fb"}]
        foreign-index (subject/one-to-one-index-on foreign-table :id)]

    (subject/extend-map original-map :using foreign-index :via :foreign_id
                        :keys [:val] :prefix "foreign-")
    => {:id 1 :foreign_id "a" :rest ..rest1.. :foreign-val "fa"}))

(fact "one-to-one tables with compound keys"
  (let [original-map {:id 1 :foreign_id_alpha "a" :foreign_id_num 1 :rest ..rest1..}
        foreign-table [{:alpha "a" :id 1 :val "fa"} {:alpha "b" :id "2" :val "fb"}]
        foreign-index (subject/one-to-one-index-on foreign-table [:alpha :id])]

    ;; TODO: This test fails under 1.6, but not 1.7 or 1.8.
    (future-fact "why does this test fail 1.6 but not 1.7 or 1.8?")
    (subject/extend-map original-map :using foreign-index :via [:foreign_id_alpha :foreign_id_num]
                        :keys [:val] :prefix "foreign-")
    => {:id 1 :foreign_id_alpha "a" :foreign_id_num 1 :rest ..rest1..
        :foreign-val "fa"}))


(fact "one-to-many tables merge under a given key"
  (let [foreign-table [{:id "a" :val "fa"} {:id "a" :val "fb"}]
        foreign-index (subject/one-to-many-index-on foreign-table :id)]

    (fact "you can add the key"
      (let [original-map {:id 1 :foreign_id "a" :rest ..rest1..}
            result (subject/extend-map original-map :using foreign-index :via :foreign_id
                                       :into :foreign-data
                                       :keys [:val] :prefix "f-")]

    (fact "you can append to existing values"
      (let [original-map {:id 1 :foreign_id "a" :rest ..rest1..
                          :foreign-data ["already here"]}
            result (subject/extend-map original-map :using foreign-index :via :foreign_id
                                       :into :foreign-data
                                       :keys [:val] :prefix "f-")]
        (:foreign-data result) => (just ["already here" {:f-val "fa"} {:f-val "fb"}]
                                        :in-any-order)))))


(fact "Everything works with string keys and prefixes"
  (future-fact "more is probably needed")
  (let [data [{"id" 1 "rest" ..rest1..} {"id" 2 "rest" ..rest2..}]
        index (subject/one-to-one-index-on data "id")]
    (fact "both can be strings"
      (subject/index-select 1 :using index :prefix "pre-") => {"pre-id" 1 "pre-rest" ..rest1..})
    (fact "note that it is the type of the original key that determines type of result key"
      (subject/index-select 1 :using index :prefix :pre-) => {"pre-id" 1 "pre-rest" ..rest1..})))
green-coder/diffuse
(ns ^:no-doc diffuse.model
  (:require [clojure.set :as set]
            [minimallist.helper :as h]))

;; A model of a diff, only used for validation.
(def diff-model
  (h/let ['key (h/fn any?)
          'value (h/fn any?)
          'index (-> (h/fn int?)
                     (h/with-condition
                       (h/fn #(>= % 0))))
          'size (h/fn pos-int?)
          'diff (h/alt [:nil (h/val nil)]
                       [:missing (h/map [:type (h/val :missing)])]
                       [:value (h/map [:type (h/val :value)]
                                      [:value (h/ref 'value)])]
                       [:set (-> (h/map
                                   [:type (h/val :set)])
                                 (h/with-optional-entries
                                   [:disj (h/set-of (h/ref 'value))]
                                   [:conj (h/set-of (h/ref 'value))])
                                 (h/with-condition
                                   (h/fn (fn [diff]
                                           (let [{disj-set :disj, conj-set :conj} diff]
                                             (and (or (seq disj-set) (seq conj-set))
                                                  (empty? (set/intersection disj-set conj-set))))))))]
                       [:map (h/map
                               [:type (h/val :map)]
                               [:key-op (-> (h/map-of (h/ref 'key)
                                                      (h/alt [:assoc (h/vector (h/val :assoc)
                                                                               (h/ref 'value))]
                                                             [:update (h/vector (h/val :update)
                                                                                (h/ref 'diff))]
                                                             [:dissoc (h/vector (h/val :dissoc))]))
                                            (h/with-condition
                                              (h/fn (fn [key-op]
                                                      (pos? (count key-op))))))])]
                       [:vector (h/map
                                  [:type (h/val :vector)]
                                  [:index-op (-> (h/vector-of (h/alt [:no-op (h/vector (h/val :no-op)
                                                                                       (h/ref 'size))]
                                                                     [:update (h/vector (h/val :update)
                                                                                        (h/in-vector (h/+ (h/ref 'diff))))]
                                                                     [:remove (h/vector (h/val :remove)
                                                                                        (h/ref 'size))]
                                                                     [:insert (h/vector (h/val :insert)
                                                                                        (h/in-vector (h/+ (h/ref 'value))))]))
                                                 (h/with-condition
                                                   (h/fn (fn [index-op]
                                                           (pos? (count index-op))))))])])]
         (h/ref 'diff)))
stuarthalloway/exploring-clojure
(ns exploring.persistent-data-structures
  (:require
   [clojure.repl :refer :all]
   [clojure.set :as set]))

;; N.B. keys are indexes
(contains? v 0)