Keep console io in atom

Keep console io in atom

--- src/clojure/nightcode/core.clj
+++ src/clojure/nightcode/core.clj
@@ -20,7 +20,7 @@
   [console console-io]
   (let [project-tree (s/tree :id :project-tree :focusable? true)
         create-new-project! (fn [_]
-                              (try (p/new-project! console-io)
+                              (try (p/new-project! @console-io)
                                 (catch Exception e (.enterLine console ""))))
         btn-group (s/horizontal-panel
                     :items [(ui/button :id :new-project-button
@@ -74,7 +74,8 @@
   [process console console-io]
   (let [run (fn [& _]
               (s/request-focus! (-> console .getViewport .getView))
-              (lein/run-repl! process console-io))]
+              (reset! console-io (ui/get-io! console))
+              (lein/run-repl! process @console-io))]
     (run)
     (doto (s/config! console :id :repl-console)
       (shortcuts/create-mappings! {:repl-console run}))))
@@ -94,7 +95,7 @@
   []
   (let [process (atom nil)
         console (ui/create-console)
-        console-io (ui/get-io! console)]
+        console-io (atom nil)]
     (s/left-right-split
       (s/top-bottom-split (get-project-pane console console-io)
                           (get-repl-pane process console console-io)


update

update

--- src/clojure/nossal/coupons.clj
+++ src/clojure/nossal/coupons.clj
@@ -23,9 +23,9 @@
              :description "💲 Ganhe R$20,00 de desconto em 2 primeiras viagens! ✅"
              :text [:p "Ganhe " [:span.value "R$10,00"]" de desconto nas suas " [:strong "2 primeiras"] " corridas! " [:ruby "🎉 " [:rt "ta-da!"]]
                      [:small "Este cupom pode ser utilizado duas vezes por pessoa, nas suas primeiras viagens. São " [:span.value "R$20,00"] " de desconto em duas viagens."]]}
-   "uber-1" {:code "0018f1"
+   "uber-1" {:code "uvejzn"
              :title ["Uber" "#2"]
-             :url "https://www.uber.com/invite/0018f1"
+             :url "https://www.uber.com/invite/uvejzn"
              :description "💲 Ganhe R$10,00 de desconto em 2 primeiras viagens! ✅"
              :text [:p "Ganhe " [:span.value "R$10,00"]" de desconto nas suas " [:strong "2 primeiras"] " corridas! " [:ruby "🎉 " [:rt "ta-da!"]]
                      [:small "Este cupom pode ser utilizado duas vezes por pessoa, nas suas primeiras viagens. São " [:span.value "R$20,00"] " de desconto em duas viagens."]]}


Fix offset on next link.

Fix offset on next link.

Fixes #120.

The next link now increases the offset by the amount of limit instead of
hardcoded 25.

--- src/statuses/routing.clj
+++ src/statuses/routing.clj
@@ -50,7 +50,7 @@
         (assoc-in ~@body [:headers "etag"] etag-str#))))

 (defn updates-page [params request]
-  (let [next (next-uri (update-in params [:offset] #(+ 25 %)) request)
+  (let [next (next-uri (update-in params [:offset] (partial + (:limit params))) request)
         {:keys [limit offset author query format]} params]
     (with-etag request (:time (first (core/get-latest @db 1 offset author query)))
       (let [items (->> (core/get-latest @db limit offset author query)


Fix query+scan selects, add asserts for malformed maps, housekeeping

--- src/taoensso/faraday.clj
+++ src/taoensso/faraday.clj
@@ -215,6 +215,8 @@
     ;; TODO Better way of grouping responses & unprocessed-keys? Might not be
     ;; possible unless we force the inclusion of the prim-kvs in :attrs.
     {:responses         (utils/keyword-map as-map (.getResponses       r))
+
+     ;; TODO Could wrap as metadata?
      :unprocessed-keys  (utils/keyword-map as-map (.getUnprocessedKeys r))
      :consumed-capacity (.getConsumedCapacity r)})
   BatchWriteItemResult
@@ -268,14 +270,19 @@
   "Returns a [{<hash-key> KeySchemaElement}], or
              [{<hash-key> KeySchemaElement} {<range-key> KeySchemaElement}]
    vector for use as a table/index primary key."
-  [hash-keydef & [range-keydef]]
-  (let [schema [(key-schema-element (:name hash-keydef) :hash)]]
-    (if range-keydef
-      (conj schema (key-schema-element (:name range-keydef) :range))
-      schema)))
+  [{hash-key-name :name :as hash-keydef} &
+   [{range-key-name :name :as range-keydef}]]
+  (assert (and hash-key-name (when range-keydef range-key-name))
+          (assert (str "Malformed key schema: "
+                       {:hash-keydef  hash-keydef
+                        :range-keydef range-keydef})))
+  (cond-> [(key-schema-element hash-key-name :hash)]
+          range-keydef (conj (key-schema-element range-key-name :range))))

 (defn- provisioned-throughput "Returns a new ProvisionedThroughput object."
-  [{read-units :read write-units :write}]
+  [{read-units :read write-units :write :as throughput}]
+  (assert (and read-units write-units)
+          (str "Malformed throughput: " throughput))
   (doto (ProvisionedThroughput.)
     (.setReadCapacityUnits  (long read-units))
     (.setWriteCapacityUnits (long write-units))))
@@ -287,6 +294,7 @@
                   (filterv identity))]
     (mapv
      (fn [{key-name :name key-type :type :as def}]
+       (assert (and key-name key-type) (str "Malformed def: " def))
        (doto (AttributeDefinition.)
          (.setAttributeName (name key-name))
          (.setAttributeType (utils/enum key-type))))
@@ -300,6 +308,8 @@
         :keys [range-keydef projection]
         :or   {projection :all}
         :as   index}]
+     (assert (and index-name range-keydef projection)
+             (str "Malformed index: " index))
      (doto (LocalSecondaryIndex.)
        (.setIndexName  (name index-name))
        (.setKeySchema  (key-schema hash-keydef range-keydef))
@@ -507,7 +517,8 @@
   [conditions]
   (when (seq conditions)
     (utils/name-map
-     (fn [[operator values]]
+     (fn [[operator values :as condition]]
+       (assert (coll? values) (str "Malformed condition: " condition))
        (doto (Condition.)
          (.setComparisonOperator (enum-op operator))
          (.setAttributeValueList (mapv clj-val->db-val values))))
@@ -515,7 +526,7 @@

 (defn query
   "Retries items from a table (indexed) with options:
-    prim-key-conds - {<key-attr> [comparison-operator <values>] ...}.
+    prim-key-conds - {<key-attr> [<comparison-operator> <values>] ...}.
     :last-prim-kvs - primary key-val from which to eval, useful for paging.
     :return        - e/o #{:all-attributes :all-projected-attributes :count
                            [<attr> ...]}.
@@ -524,26 +535,29 @@
     :limit         - max num >=1 of items to eval (≠ num of matching items).
     :consistent?   - use strongly (rather than eventually) consistent reads?

+  comparison-operators e/o #{:eq :le :lt :ge :gt :begins-with :between}.
+
   For unindexed item retrievel see `scan`."
   [creds table prim-key-conds
    & [{:keys [last-prim-kvs return index order limit consistent?]
        :or   {order :asc}}]]
+  (println (query|scan-conditions prim-key-conds))
   (as-map
    (.query (db-client creds)
      (doto-maybe (QueryRequest.) g
        :always (.setTableName        (name table))
        :always (.setKeyConditions    (query|scan-conditions prim-key-conds))
        :always (.setScanIndexForward (case order :asc true :desc false))
-       last-prim-kvs (.setExclusiveStartKey (clj-item->db-item g))
-       limit         (.setLimit    (long g))
-       index         (.setIndexName      g)
-       consistent?   (.setConsistentRead g)
-       (coll? return)       (.setAttributesToGet (mapv name return))
-       (not (coll? return)) (.setSelect (utils/enum return))))))
+       last-prim-kvs  (.setExclusiveStartKey (clj-item->db-item g))
+       limit          (.setLimit    (long g))
+       index          (.setIndexName      g)
+       consistent?    (.setConsistentRead g)
+       (coll? return) (.setAttributesToGet (mapv name return))
+       (and return (not (coll? return))) (.setSelect (utils/enum return))))))

 (defn scan
   "Retrieves items from a table (unindexed) with options:
-    :attr-conds     - {<attr> [comparison-operator <values>] ...}.
+    :attr-conds     - {<attr> [<comparison-operator> <values>] ...}.
     :limit          - max num >=1 of items to eval (≠ num of matching items).
     :last-prim-kvs  - primary key-val from which to eval, useful for paging.
     :return         - e/o #{:all-attributes :all-projected-attributes :count
@@ -551,11 +565,13 @@
     :total-segments - total number of parallel scan segments.
     :segment        - calling worker's segment number (>=0, <=total-segments).

+  comparison-operators e/o #{:eq :le :lt :ge :gt :begins-with :between :ne
+                             :not-null :null :contains :not-contains :in}.
+
   For automatic parallelization & segment control see `scan-parallel`.
   For indexed item retrievel see `query`."
   [creds table
-   & [{:keys [attr-conds last-prim-kvs return limit total-segments segment]
-       :or   {return :all-attributes}}]]
+   & [{:keys [attr-conds last-prim-kvs return limit total-segments segment]}]]
   (as-map
    (.scan (db-client creds)
      (doto-maybe (ScanRequest.) g
@@ -565,8 +581,8 @@
        limit          (.setLimit             (long g))
        total-segments (.setTotalSegments     (long g))
        segment        (.setSegment           (long g))
-       (coll? return)       (.setAttributesToGet (mapv name return))
-       (not (coll? return)) (.setSelect (utils/enum return))))))
+       (coll? return) (.setAttributesToGet (mapv name return))
+       (and return (not (coll? return))) (.setSelect (utils/enum return))))))

 (defn scan-parallel
   "Like `scan` but starts a number of worker threads and automatically handles


Update catacumba version on debugging example.

--- examples/debugging/project.clj
+++ examples/debugging/project.clj
@@ -4,7 +4,7 @@
   :license {:name "BSD (2-Clause)"
             :url "http://opensource.org/licenses/BSD-2-Clause"}
   :dependencies [[org.clojure/clojure "1.7.0-RC1"]
-                 [funcool/catacumba "0.1.0-alpha2"]
+                 [funcool/catacumba "0.2.0"]
                  [prone "0.8.1"]]
   :main ^:skip-aot debugging.core
   :target-path "target/%s"


fixed pacman always trying to install package groups

--- src/duffel/ext/impl/pacman.clj
+++ src/duffel/ext/impl/pacman.clj
@@ -8,8 +8,18 @@
   (split (slurp file) #"\n"))

 (defn- package-installed?
+  "Returns true if a package is currently installed through pacman, false if
+  not"
   [pac]
-  (try (exec "sudo" "pacman" "-Q" pac) true
+  (try (exec "pacman" "-Q" pac) true
+  (catch Exception _ false)))
+
+(defn- any-from-group-installed?
+  "Returns true if any packages in the given group have been installed, false if
+  not. Ideally the whole group should be checked to see if it's installed, but
+  it's non-trivial to find that out with pacman"
+  [group]
+  (try (exec "pacman" "-Qg" group) true
   (catch Exception _ false)))

 (defn- install-packages!
@@ -24,7 +34,8 @@
         pacs (->> all-pacs
                   (remove #(= (first %) \#))
                   (remove empty?)
-                  (remove package-installed?))]
+                  (remove package-installed?)
+                  (remove any-from-group-installed?))]
     (if-not (empty? pacs)
       (apply install-packages! util pacs opts)
       [0 "" ""])))


Convert to using defdbtest, removing unneeded cleanup code.

--- clj_record/test/core_test.clj
+++ clj_record/test/core_test.clj
@@ -36,40 +36,31 @@
   (let [humedai (manufacturer/create {:name "Humedai Motors"})]
     (is (= humedai (manufacturer/get-record (:id humedai))))))

-(deftest get-record-throws-if-not-found
+(defdbtest get-record-throws-if-not-found
   (is (thrown? IllegalArgumentException (manufacturer/get-record -1))))

-(deftest find-records-by-attribute-equality-conditions
+(defdbtest find-records-by-attribute-equality-conditions
   (let [humedai (manufacturer/create {:name "Humedai Motors"})
         other-1 (manufacturer/create {:name "Some Other"})]
-    (try
-      (is (= [humedai] (manufacturer/find-records {:name "Humedai Motors"})))
-      (finally
-        (manufacturer/destroy-record humedai)
-        (manufacturer/destroy-record other-1)))))
+    (is (= [humedai] (manufacturer/find-records {:name "Humedai Motors"})))))

-(deftest find-records-by-SQL-conditions
+(defdbtest find-records-by-SQL-conditions
   (let [humedai (manufacturer/create {:name "Humedai Motors"})
         other-1 (manufacturer/create {:name "Some Other"})]
-    (try
-      (is (= [humedai] (manufacturer/find-records ["name = ?" "Humedai Motors"])))
-      (finally
-        (manufacturer/destroy-record humedai)
-        (manufacturer/destroy-record other-1)))))
+    (is (= [humedai] (manufacturer/find-records ["name = ?" "Humedai Motors"])))))

-(deftest destroy-record-destroys-by-id-from-record
+(defdbtest destroy-record-destroys-by-id-from-record
   (let [humedai (manufacturer/create {:name "Humedai Motors"})]
     (manufacturer/destroy-record {:id (:id humedai)})
     (is (empty? (manufacturer/find-records {:id (:id humedai)})))))

-(deftest update-uses-id-to-update-other-given-attributes-leaving-unspecified-attributes-untouched
+(defdbtest update-uses-id-to-update-other-given-attributes-leaving-unspecified-attributes-untouched
   (let [humedai (manufacturer/create {:name "Humedai Motors" :grade 90})
         id (:id humedai)]
     (manufacturer/update {:id id :name "Schmoomdai Motors" :founded "2008"})
     (is (=
       {:name "Schmoomdai Motors" :grade 90 :founded "2008"}
-      (select-keys (manufacturer/get-record id) [:name :grade :founded])))
-    (manufacturer/destroy-record humedai)))
+      (select-keys (manufacturer/get-record id) [:name :grade :founded])))))

 (deftest to-conditions
   (are (= _1 (core/to-conditions _2))


Added the all-important catchphrase.

Added the all-important catchphrase.

--- src/ackbar/core.clj
+++ src/ackbar/core.clj
@@ -1,3 +1,5 @@
+;; It's a Trap!
+
 (ns ackbar.core
   (:use compojure.core hiccup.core hiccup.form-helpers hiccup.page-helpers)
   (:require [appengine-magic.core :as ae]))
@@ -76,4 +78,4 @@
   (GET "/:name" [name] (render-page (canonical-name name)))
   (ANY "*" [] (render-page "404")))

-(ae/def-appengine-app ackbar-app #'ackbar-app-handler)+(ae/def-appengine-app ackbar-app #'ackbar-app-handler)


adds note

adds note

--- src/advent/core.clj
+++ src/advent/core.clj
@@ -257,7 +257,7 @@
   find-signal
   (memoize (fn
              [signal circuit]
-             (if (integer? (signal circuit))
+             (if (integer? (signal circuit))  ; N.B. could also switch on the type here
                (signal circuit)
                (if (string? (signal circuit))  ; either a string, "lx", or array, ["x" "LSHIFT" "y"] or ["NOT" "x"]
                  (find-signal (keyword (signal circuit)) circuit)


add tar extraction

add tar extraction

--- src/aurman/core.clj
+++ src/aurman/core.clj
@@ -1,7 +1,9 @@
 (ns aurman.core
   (:gen-class)
   (:use aurman.api)
-  (:use [me.raynes/fs]))
+  (:require [me.raynes.fs :as fs]
+            [me.raynes.fs.compression :as compr])
+  (:use [clojure.java.shell :only [sh]]))

 (def pkg-dir "/tmp")

@@ -29,15 +31,29 @@
          (if more (recur more)))
           res))))

+(defn extract
+  [filename filepath outdir]
+  (let [target (str outdir
+                    "/"
+                    (clojure.string/replace filename #"\.gz$" ""))]
+    (println "Extracting " filepath "into" target)
+    (compr/gunzip filepath target)
+    (println "Extracting " target "into" outdir)
+    (compr/untar target outdir)
+    (println "Deleting " target)
+    (fs/delete target)
+))
+
 (defn install
   [pkg]
   (do
     (println pkg)
     (let [[f bytes] (get-pkg pkg)
-           filepath (str pkg-dir "/" f)]
+           filepath (str pkg-dir "/" f)
+           target (clojure.string/replace filepath #"\.tar\.gz$" "/")]
       (println filepath)
       (save-file filepath bytes)
-      (fs/untar filepath pkg-dir))))
+      (extract f filepath pkg-dir))))

 (defn aur-search
   [query]


HDM-UML-fin

HDM-UML-fin

--- hdm-uml-model.clj
+++ hdm-uml-model.clj
@@ -1,6 +1,28 @@
+
+(def-class :Extension
+  (with-attributes
+    :LocalID
+    :Key
+    :Value))
+
+(def-class :Entity
+  (with-attributes
+    :ID
+    :Validity
+    :CreationTime
+    :OtherInfo
+    :Name))
+
+(def-class :Domain
+  (with-attributes
+    :WWW
+    :Description)
+  (extends :Entity))
+
 (def-class :Share
   (with-attributes
-    :Description))
+    :Description)
+  (extends :Entity))

 (def-class :Service
   (with-attributes
@@ -8,7 +30,8 @@
     :QualityLevel
     :Capability
     :Type
-    :Complexity))
+    :Complexity)
+  (extends :Entity))

 (def-class :Location
   (with-attributes
@@ -17,43 +40,36 @@
     :PostCode
     :Country
     :Place
-    :Address))
+    :Address)
+  (extends :Entity))

 (def-class :AdminDomain
   (with-attributes
     :Distributed
-    :Owner))
-
-(def-class :Domain
-  (with-attributes
-    :WWW
-    :Description))
-
-(def-class :Entity
-  (with-attributes
-    :ID
-    :Validity
-    :CreationTime
-    :OtherInfo
-    :Name))
-
-(def-class :Extension
-  (with-attributes
-    :LocalID
-    :Key
-    :Value))
+    :Owner)
+  (extends :Domain)) ;Pytanie, czy robimy podwójne dziedziczenie, czy wystarczy nam, że już :Domain dziedziczy po :Entity
+
+(def-class :UserDomain
+  (with-attributes
+    :Member
+    :UserManager
+    :Level)
+  (extends :Domain))

 (def-class :Contact
   (with-attributes
     :Type
-    :Detail))
+    :Detail)
+  (extends :Entity))

 (def-class :Manager
   (with-attributes
     :ProductVersion
-    :ProductName))
-
-(def-class :Resource)
+    :ProductName)
+  (extends :Entity))
+
+(def-class :Resource
+  (extends :Entity))

 (def-class :Endpoint
   (with-attributes
@@ -78,25 +94,24 @@
     :ImplementationName
     :ImplementationVersion
     :DowntimeEnd
-    :TrustedCA))
-
-(def-class :Activity)
+    :TrustedCA)
+  (extends :Entity))
+
+(def-class :Activity
+  (extends :Entity))

 (def-class :Policy
   (with-attributes
     :Rule
-    :Scheme))
-
-(def-class :AccessPolicy)
-
-(def-class :MappingPolicy)
-
-
-(def-class :UserDomain
-  (with-attributes
-    :Member
-    :UserManager
-    :Level))
+    :Scheme)
+  (extends :Entity))
+
+(def-class :AccessPolicy
+  (extends :Policy))
+
+(def-class :MappingPolicy
+  (extends :Policy))
+

 (association ""
   "role1" :Extension 1 1
@@ -106,6 +121,99 @@
 (association "ParticipatesIn"
   "role1" :UserDomain 1 *)

+(association "Creates"
+  "role1" :Activity 1 *
+  "role2" :UserDomain 0 *)
+
 (association "HasPolicies"
   "role1" :UserDomain 0 *
-  "role2" :Policy 0 1)+  "role2" :Policy 0 1)
+
+(association "Has"
+  "role1" :Contact 0 *
+  "role2" :Domain 0 *)
+
+(association "Has"
+  "role1" :Contact 0 *
+  "role2" :Service 0 *)
+
+(association "PrimarilyLocatedAt"
+  "role1" :Domain 1 *
+  "role2" :Location 0 *)
+
+(association "PrimarilyLocatedAt"
+  "role1" :Service 1 *
+  "role2" :Location 0 *)
+
+(association "RelatesTo"
+  "role1" :Service 0 *)
+
+(association "ParticipatesIn"
+  "role1" :AdminDomain 1 *)
+
+(association "Manages"
+  "role1" :AdminDomain 0 *
+  "role2" :Service 0 *)
+
+(association "Manages"
+  "role2" :Manager 0 1
+  "role1" :Resource 0 *)
+
+(association "Offers"
+  "role1" :Service 0 *
+  "role2" :Manager 1 1)
+
+(association "Offers"
+  "role1" :Service 0 *
+  "role2" :Share 1 1)
+
+(association "Exposes"
+  "role1" :Service 0 *
+  "role2" :Endpoint 1 1)
+
+(association "CanBeMappedInto"
+  "role1" :MappingPolicy 1 1
+  "role2" :Share)
+
+(association "CanAccess"
+  "role1" :AccessPolicy 1 1
+  "role2" :Endpoint 0 *)
+
+(association "DefinedOn"
+  "role1" :Share 0 *
+  "role2" :Resource 0 *)
+
+(association "Offers"
+  "role1" :Endpoint 0 *
+  "role2" :Share)
+
+(association "SubmittedBy"
+  "role1" :Endpoint 0 *
+  "role2" :Activity 1 *)
+
+(association "MappedInto"
+  "role1" :Activity 1 *
+  "role2" :Resource 0 *)
+
+(association "Runs"
+  "role1" :Activity 1 *
+  "role2" :Share 0 *)
+
+(association "RelatesTo"
+  "role1" :Activity 0 *)
+
+
+;---------------------------------------------------------------------------------------------------------------
+;temporary, to be resolved solution
+
+(generalization
+  (into :Policy)
+  (from :MappingPolicy :AccessPolicy))
+
+(generalization
+  (into :Domain)
+  (from :AdminDomain :UserDomain))
+
+(genralization
+  (into :Entity)
+  (from :Domain :Policy :Endpoint :Contact :Location :Service :Share :Resource :Activity :Manager))


only :advanced has variable maps

only :advanced has variable maps

--- src/main/shadow/cljs/build.clj
+++ src/main/shadow/cljs/build.clj
@@ -635,7 +635,8 @@
                                   (throw
                                     (ex-info
                                       (format "ns \"%s\" not available, required by %s" require-sym name)
-                                      {:ns require-sym
+                                      {:tag ::missing-ns
+                                       :ns require-sym
                                        :src name})))
                                 src-name
                                 )))
@@ -675,7 +676,7 @@
                       (filter #(contains? (:requires %) ns-sym))
                       (map :name)
                       (into #{}))]
-        (throw (ex-info (format "ns \"%s\" not available, required by %s" ns-sym reqs) {:ns ns-sym :required-by reqs}))))
+        (throw (ex-info (format "ns \"%s\" not available, required by %s" ns-sym reqs) {:tag ::missing-ns :ns ns-sym :required-by reqs}))))

     (get-deps-for-src state name)
     ))
@@ -2285,7 +2286,8 @@
             (spit target source-map-json)))))

     ;; with-logged-time expects that we return the compiler-state
-    state))
+    state
+    ))

 (defn load-externs [{:keys [externs build-modules] :as state}]
   (let [externs
@@ -2326,7 +2328,6 @@
          (into []))
     ))

-
 ;; added by default in init-state
 (defn closure-add-replace-constants-pass [cc ^CompilerOptions co state]
   (.addCustomPass co CustomPassExecutionTime/BEFORE_CHECKS (ReplaceCLJSConstants. cc)))
@@ -2341,15 +2342,16 @@
           nil)))))

 (defn write-variable-map [{:keys [cache-dir] :as state} name map]
-  (let [map-file
-        (doto (io/file cache-dir name)
-          (io/make-parents))
-
-        bytes
-        (ByteArrayInputStream. (.toBytes map))]
-
-    (with-open [out (FileOutputStream. map-file)]
-      (io/copy bytes out))))
+  (when map
+    (let [map-file
+          (doto (io/file cache-dir name)
+            (io/make-parents))
+
+          bytes
+          (ByteArrayInputStream. (.toBytes map))]
+
+      (with-open [out (FileOutputStream. map-file)]
+        (io/copy bytes out)))))

 (defn closure-add-variable-maps [cc co {:keys [cache-dir] :as state}]
   (when-some [data (read-variable-map state "closure.property.map")]
@@ -2659,7 +2661,6 @@
           out)]

     (spit target out)))
-

 (defn flush-unoptimized!
   [{:keys [build-modules public-dir] :as state}]


Call out that batch methods are not atomic.

--- src/blocks/core.clj
+++ src/blocks/core.clj
@@ -289,18 +289,26 @@

 (defn put-batch!
   "Saves a collection of blocks into the store. Returns a sequence of the
-  stored blocks, in no particular order."
+  stored blocks, in no particular order.
+
+  This is not guaranteed to be an atomic operation; readers may be able to see
+  the store in a partially-updated state."
   [store blocks]
   (validate-collection-of Block blocks)
-  (if (satisfies? store/BatchingStore store)
-    (seq (store/-put-batch! store blocks))
-    (doall (map (partial put! store) blocks))))
+  (if-let [blocks (seq (remove nil? blocks))]
+    (if (satisfies? store/BatchingStore store)
+      (store/-put-batch! store blocks)
+      (mapv (partial put! store) blocks))
+    []))

 (defn delete-batch!
   "Removes a batch of blocks from the store, identified by a collection of
   multihashes. Returns a set of ids for the blocks which were found and
-  deleted."
+  deleted.
+
+  This is not guaranteed to be an atomic operation; readers may be able to see
+  the store in a partially-deleted state."
   [store ids]
   (validate-collection-of Multihash ids)
   (if (satisfies? store/BatchingStore store)
@@ -313,7 +321,7 @@

 (defn erase!!
   "Completely removes any data associated with the store. After this call, the
-  store should be empty."
+  store should be empty. This is not guaranteed to be an atomic operation!"
   [store]
   (if (satisfies? store/ErasableStore store)
     (store/-erase! store)


Reorganized init function calling to permit texture initialization in user-initialization function.

--- src/brevis/core.clj
+++ src/brevis/core.clj
@@ -61,6 +61,14 @@
   state
   #_(glfx/enable-high-quality-rendering))

+(defn make-init
+  "Make an initialize function based upon a user-customized init function."
+  [user-init]
+  (fn [state]
+    (init state)
+    (user-init)
+    state))
+
 (def shift-key-down (atom false))
 (defn sin [n] (float (Math/sin n)))
 (defn cos [n] (float (Math/cos n)))
@@ -294,16 +302,15 @@
   ([initialize update]
     (reset-core)
 	  (app/start
-	   {:reshape reshape, :init init, :mouse-drag mouse-drag, :key-press key-press :mouse-wheel mouse-wheel, :update update, :display display
+	   {:reshape reshape, :init (make-init initialize), :mouse-drag mouse-drag, :key-press key-press :mouse-wheel mouse-wheel, :update update, :display display
 	    :key-release key-release
 	    ;:mouse-move    (fn [[[dx dy] [x y]] state] (println )
 	    ;:mouse-up       (fn [[x y] button state] (println button) state)
 	    ;:mouse-click   (fn [[x y] button state] (println button) state)
 	    ;:mouse-down    (fn [[x y] button state] (println button) state)
 	    ;:mouse-wheel   (fn [dw state] (println dw) state)
-	    }
-    (do (initialize)
-      @*gui-state*))))
+	    }
+    @*gui-state*)))

 #_(defn start-nogui [iteration-step-size]


Refactor virtual peer after cleanup

Refactor virtual peer after cleanup

--- src/onyx/peer/virtual_peer.clj
+++ src/onyx/peer/virtual_peer.clj
@@ -6,7 +6,6 @@
             [taoensso.timbre :as timbre :refer [info]]
             [onyx.peer.operation :as operation]
             [onyx.log.entry :refer [create-log-entry]]
-            [onyx.log.commands.task-state :refer [stop-task-state]]
             [onyx.static.default-vals :refer [defaults arg-or-default]]))

 (defn send-to-outbox! [{:keys [outbox-ch] :as state} reactions]
@@ -23,24 +22,21 @@
       (assoc peer-annotated :entry-parent message-id)
       peer-annotated)))

-(defn processing-loop [id log messenger origin inbox-ch outbox-ch restart-ch kill-ch opts monitoring task-component-fn]
-  (let [replica-atom (atom origin)
-        task-state-atom (atom nil)]
+(defn processing-loop [id log peer-group origin inbox-ch outbox-ch restart-ch kill-ch opts monitoring task-component-fn]
+  (let [replica-atom (atom origin)]
     (try
       (loop [state {:id id
                     :task-component-fn task-component-fn
                     :replica replica-atom
-                    :task-state task-state-atom
                     :log log
                     :buffered-outbox []
-                    :messenger messenger
+                    :peer-group peer-group
                     :monitoring monitoring
                     :outbox-ch outbox-ch
                     :opts opts
                     :kill-ch kill-ch
                     :restart-ch restart-ch}]
         (let [replica @replica-atom
-              task-state @task-state-atom
               [entry ch] (alts!! [kill-ch inbox-ch] :priority true)]
           (cond
             (instance? java.lang.Throwable entry)
@@ -49,20 +45,18 @@
             (when (:lifecycle state)
               (component/stop @(:lifecycle state)))
             :else
-            (let [new-replica (extensions/apply-log-entry entry replica)
+            (let [new-replica (assoc (extensions/apply-log-entry entry replica)
+                                     :version (:message-id entry))
                   diff (extensions/replica-diff entry replica new-replica)
                   reactions (extensions/reactions entry replica new-replica diff state)
                   new-state (extensions/fire-side-effects! entry replica new-replica diff state)
-                  new-task-state (extensions/new-task-state! log entry replica new-replica diff new-state task-state opts)
                   annotated-reactions (mapv (partial annotate-reaction entry id) reactions)]
               (reset! replica-atom new-replica)
-              (reset! task-state-atom new-task-state)
               (recur (send-to-outbox! new-state annotated-reactions))))))
       (catch Throwable e
         (taoensso.timbre/error e (format "Peer %s: error in processing loop. Restarting." id))
         (close! restart-ch))
       (finally
-        (stop-task-state @task-state-atom)
         ;; call peer replica view side effects shutdown stuff here
         (taoensso.timbre/info (format "Peer %s: finished of processing loop" id))))))

@@ -78,10 +72,10 @@
     (finally
       (taoensso.timbre/info (format "Peer %s: finished outbox loop" id)))))

-(defrecord VirtualPeer [opts task-component-fn]
+(defrecord VirtualPeer [opts peer-group task-component-fn]
   component/Lifecycle

-  (start [{:keys [log messenger monitoring] :as component}]
+  (start [{:keys [log monitoring] :as component}]
     (let [id (java.util.UUID/randomUUID)]
       (taoensso.timbre/info (format "Starting Virtual Peer %s" id))
       (try
@@ -95,7 +89,7 @@
               outbox-ch (chan (arg-or-default :onyx.peer/outbox-capacity opts))
               kill-ch (chan (dropping-buffer 1))
               restart-ch (chan 1)
-              peer-site (m/peer-site messenger)
+              peer-site (m/peer-site (:messaging-group peer-group) id)
               entry (create-log-entry :prepare-join-cluster {:joiner id :peer-site peer-site
                                                              :tags (or (:onyx.peer/tags opts) [])})
               origin (extensions/subscribe-to-log log inbox-ch)]
@@ -103,7 +97,7 @@
           (>!! outbox-ch entry)

           (let [outbox-loop-ch (thread (outbox-loop id log outbox-ch restart-ch))
-                processing-loop-ch (thread (processing-loop id log messenger origin inbox-ch outbox-ch restart-ch kill-ch opts monitoring task-component-fn))]
+                processing-loop-ch (thread (processing-loop id log peer-group origin inbox-ch outbox-ch restart-ch kill-ch opts monitoring task-component-fn))]
             (assoc component
                    :outbox-loop-ch outbox-loop-ch
                    :processing-loop-ch processing-loop-ch
@@ -128,5 +122,5 @@
            :kill-ch nil :restart-ch nil
            :outbox-loop-ch nil :processing-loop-ch nil)))

-(defn virtual-peer [opts task-component-fn]
-  (map->VirtualPeer {:opts opts :task-component-fn task-component-fn}))
+(defn virtual-peer [opts peer-group task-component-fn]
+  (map->VirtualPeer {:opts opts :peer-group peer-group :task-component-fn task-component-fn}))


take-segments! should reset timeout channel on reading each message

--- src/onyx/plugin/core_async.clj
+++ src/onyx/plugin/core_async.clj
@@ -139,16 +139,14 @@
    Returns a seq of segments, including :done."
   ([ch] (take-segments! ch nil))
   ([ch timeout-ms]
-   (when-let [tmt (if timeout-ms
-                    (timeout timeout-ms)
-                    (chan))]
-     (loop [ret []]
-       (let [[v c] (alts!! [ch tmt] :priority true)]
-         (if (= c tmt)
-           ret
-           (if (and v (not= v :done))
-             (recur (conj ret v))
-             (conj ret :done))))))))
+   (loop [ret []]
+     (let [tmt (if timeout-ms (timeout timeout-ms) (chan))
+           [v c] (alts!! [ch tmt] :priority true)]
+       (if (= c tmt)
+         ret
+         (if (and v (not= v :done))
+           (recur (conj ret v))
+           (conj ret :done)))))))

 (def channels (atom {}))


differentiate media errors

differentiate media errors

--- src/cellf/core.cljs
+++ src/cellf/core.cljs
@@ -223,7 +223,7 @@
                 :show-about?  true})
               (js/setTimeout start! 500))))
           (aset "src" data)))
-      (swap! app-state assoc :media-error? true)))))
+      (swap! app-state assoc :media-error data)))))

 (defn make-gif [app ms]
@@ -241,12 +241,16 @@
   (let [winner?    (and cells (= cells win-state))
         no-stream? (not stream)]
     (dom/div #js {
-      :className (str "modal" (when (or no-stream? media-error? show-about? winner?) " active"))}
+      :className (str "modal" (when (or no-stream? media-error show-about? result-gif winner?) " active"))}
       (dom/h1 nil "Cellf")
       (cond
-        media-error?
+        media-error
           (dom/p nil
-            "Sorry, Cellf doesn't work without camera access."
+            (if (= media-error :denied)
+              "Sorry, Cellf doesn't work without camera access."
+              (str
+                "Sorry, it looks like your device or browser doesn't support camera access. "
+                "Try Cellf using Chrome or Firefox on a device that supports WebRTC."))
             (dom/button #js {:onClick get-camera!} "try again"))

         no-stream?


Match probemap exact name or name+assembly.

--- src/cgdata/core.clj
+++ src/cgdata/core.clj
@@ -95,7 +95,9 @@

 (defn- json-add [acc [file {n "name" t "type" :as metadata}]]
   (if-let [group (and (= t "probeMap") (metadata "group"))]
-    (assoc-in acc [t (str group "::" (metadata ":assembly"))] file)
+    (-> acc
+        (assoc-in [t (str group "::" (metadata ":assembly"))] file)
+        (assoc-in [t n] file))
     (assoc-in acc [t n] file)))

 (defn- json-table [json-list]


require game ns in dev/user.clj

require game ns in dev/user.clj

--- dev/user.clj
+++ dev/user.clj
@@ -5,7 +5,8 @@
             [clojure.repl :refer :all]
             [clojure.test :as test]
             [clojure.tools.namespace.repl :refer (refresh refresh-all)]
-            [ji.system :as system]))
+            [ji.system :as system]
+            [ji.domain.game :as game]))

 (def system nil)


adds line reader

adds line reader

--- src/advent/core.clj
+++ src/advent/core.clj
@@ -272,4 +272,10 @@

 ; Day 19
 (def day-19-subs "/Users/alandgraf/code/advent/day19-substitutions.txt")
-(def day-19-molecule "/Users/alandgraf/code/advent/day19-molecule.txt")+(def day-19-molecule "/Users/alandgraf/code/advent/day19-molecule.txt")
+(use 'clojure.java.io)
+
+(defn print-file-contents [filename]
+  (with-open [rdr (reader filename)]
+    (doseq [line (line-seq rdr)]
+      (println line))) )


+(comp-pre-checks2): for now, only used for diagnostics

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -121,6 +121,42 @@
    (fail? (unifyc (get-in parent [:head :synsem :subcat :2] :top)
                   (get-in child [:synsem :subcat :2] :top)))))

+(def head-precheck-pairs
+  [[[:head :synsem :infl]       [:synsem :infl]]
+   [[:head :synsem :subcat]     [:synsem :subcat]]
+   [[:head :synsem :agr]        [:synsem :agr]]
+   [[:head :phrasal]            [:phrasal]]
+   [[:head :synsem :sem]        [:synsem :sem]]
+   [[:head :synsem :aux]        [:synsem :aux]]
+   [[:head :synsem :cat]        [:synsem :cat]]
+   [[:head :synsem :pronoun]    [:synsem :pronoun]]
+   [[:head :synsem :propernoun] [:synsem :propernoun]]
+   [[:head :synsem :subcat :1]  [:synsem :subcat :1]]
+   [[:head :synsem :subcat :2]  [:synsem :subcat :2]]])
+
+(defn head-pre-checks2 [parent child]
+  (not (nil?
+        (some #(= :fail %)
+              (map (fn [pair]
+                     (log/trace (str "head-pre-checks2: looking at pair: " pair))
+                     (let [parent-value (get-in parent (first pair) :top)
+                           child-value (get-in child (second pair) :top)
+                           result
+                           (unifyc parent-value child-value)]
+                       (log/trace (str "head-pre-checks2: result: " result))
+                       (if (fail? result)
+                         (do
+                           (log/trace (str "head precheck failed  for pair: " pair))
+                           (log/trace (str "head precheck failed: parent wanted: " (strip-refs parent-value) ";"
+                                           "child has: " (strip-refs child-value)))
+                           (log/trace (str " parent is: " (strip-refs parent)))
+                           (log/trace (str " child is: " (strip-refs child)))
+                           :fail)
+                         (do
+                           (log/trace (str "head precheck success for pair: " pair))
+                           :top))))
+                   (lazy-seq head-precheck-pairs))))))
+
 (def comp-precheck-pairs
   [{:parent [:comp :synsem :cat]
     :childc [:synsem :cat]}
@@ -150,6 +186,7 @@
                      child-value (get-in parent (:childc pair) :top)
                      result
                      (unifyc parent-value child-value)]
+                 (log/debug (str "comp-pre-checks2: result: " result))
                  (if (fail? result)
                    (do
                      (log/trace (str "comp precheck failed  for pair: " pair))
@@ -184,6 +221,8 @@
     (log/trace (str "moreover-head (candidate) parent: [" (get-in parent [:rule]) "] '" (morph parent) "' sem:    " (strip-refs (get-in parent '(:synsem :sem) :no-semantics))))
     (log/trace (str "moreover-head (candidate) head child: [" (get-in parent [:child]) "] '" (morph child) "' sem:" (strip-refs (get-in child '(:synsem :sem) :top))))
     (let [head-pre-checks (head-pre-checks parent child)
+          ;; TODO: replace head-pre-checks with head-pre-checks2
+          ;;head-pre-checks2 (head-pre-checks2 parent child)
           result
           (if head-pre-checks
             (do
@@ -257,7 +296,7 @@
   (log/trace (str "moreover-comp: child cat: " (get-in child [:synsem :cat])))
   (log/trace (str "moreover-comp: parent comp cat: " (get-in parent [:comp :synsem :cat])))

-  (let [pre-check2 (comp-pre-checks2 parent child)
+  (let [;pre-check2 (comp-pre-checks2 parent child) ;; TODO: not working yet: fix
         pre-check (comp-pre-checks parent child)

         result


Use port environment value when trying to investigate not starting on heroku

--- src/findash/web.clj
+++ src/findash/web.clj
@@ -4,6 +4,7 @@
             [compojure.handler :as handler]
             [compojure.route :as route]
             [hiccup.page :as page]
+            [environ.core :refer [env]
             [org.httpkit.server :as httpkit]
             [findash.json :as json]
             [findash.socket :as socket]


Add the ability to dump raw timings to CSV.

--- src/frmr/dstt.clj
+++ src/frmr/dstt.clj
@@ -3,7 +3,7 @@
   (:require [clj-http.client :as client]
             [clojure.tools.cli :refer [parse-opts]]
             [clojure.java.io :as io]
-            [clojure.string :refer [split]]
+            [clojure.string :refer [join split]]
             [clojure.data.json :as json])
   (:gen-class))

@@ -73,7 +73,8 @@
     {"Averages" average-per-category
      "Minimums" min-per-category
      "Maximums" max-per-category
-     "StandardDeviations" stddev-per-category}))
+     "StandardDeviations" stddev-per-category
+     "RawResults" results}))

 (defn- select-function-for-http-method
  [http-method]
@@ -147,6 +148,9 @@
     :default nil]

    ["-h" "--help"]
+
+   [nil "--csv FILE" "Spit out a CSV file with raw timings."
+    :id :csv]

    ["-v" "--verbose"]])

@@ -178,7 +182,8 @@
              http-method :method
              http-headers :headers
              http-body :body
-             verbose :verbose} (:options parsed-options)
+             verbose :verbose
+             csv :csv} (:options parsed-options)
             [url] (:arguments parsed-options)
             milliseconds (* seconds 1000)
             pause-between-requests (/ milliseconds requests)
@@ -202,6 +207,13 @@
                                                requests
                                                pause-between-requests
                                                parsed-handler)]
+          (if csv
+            (with-open [csv-writer (io/writer csv)]
+              (let [raw-results (get load-test-results "RawResults")
+                    lines (map #(join "," %) raw-results)
+                    content (join "\n" lines)]
+                (println (str "Writing CSV " csv))
+                (.write csv-writer content))))
           (println (str "Average: " (get load-test-results "Averages")))
           (println (str "Minimum: " (get load-test-results "Minimums")))
           (println (str "Maximum: " (get load-test-results "Maximums")))


Change constructors to match lazy terminology.

--- src/blocks/data.clj
+++ src/blocks/data.clj
@@ -242,9 +242,10 @@
       _attrs
       {:id id
        :size size
-       :state (cond content :literal
-                    reader  :lazy
-                    :else   :empty)}))
+       :block/state
+       (cond content :literal
+             reader  :lazy
+             :else   :empty)}))

   clojure.lang.IPending
@@ -269,6 +270,7 @@
 (defn create-literal-block
   "Creates a block by reading a source into memory. The block is given the id
   directly, without being checked."
+  ^Block
   [id source]
   (let [content (bytes/to-byte-array source)]
     (Block. id
@@ -280,6 +282,7 @@
 (defn read-literal-block
   "Creates a block by reading the source into memory and hashing it. This
   creates a realized block."
+  ^Block
   [source algorithm]
   (let [hash-fn (checked-hash algorithm)
         content (bytes/to-byte-array source)]
@@ -289,18 +292,20 @@
             nil nil nil)))

-(defn create-deferred-block
+(defn create-lazy-block
   "Creates a block from a reader function. Each time the function is called, it
   should return a new `InputStream` to read the block contents. The block is
   given the id and size directly, without being checked."
+  ^Block
   [id size reader]
   (Block. id size nil reader nil nil))

-(defn read-deferred-block
+(defn read-lazy-block
   "Creates a block from a reader function. Each time the function is called, it
   should return a new `InputStream` to read the block contents. The stream will
   be read once immedately to calculate the hash and size."
+  ^Block
   [reader algorithm]
   (let [hash-fn (checked-hash algorithm)
         counter (atom 0)]


Make derive-column support multiple arguments.

--- src/grafter/csv.clj
+++ src/grafter/csv.clj
@@ -84,7 +84,9 @@
     (apply remove-indices merged to-drop)))

 (defn fuse [csv f & cols]
-  "Merge columns with the specified function f receives the number of
+  "DEPRECATED: Use derive-column instead.
+
+Merge columns with the specified function f receives the number of
 cols supplied number of arguments e.g. If you fuse 3 columns f
 must accept 3 arguments"
   (map (partial fuse-row cols f) csv))
@@ -115,6 +117,11 @@
                        [] col-map)
          ) csv))

+(defn apply-ns [f row col-ns]
+  (->> col-ns
+       (map (partial nth row))
+       (apply f)))
+
 (defn derive-column
   "Adds a new column to the end of the row which is derived from
 column with position col-n.  f should just return the cells value.
@@ -122,12 +129,14 @@
 If no f is supplied the identity function is used, which results in
 the specified column being cloned."

-  ;; todo support multiple columns/arguments to f.
   ([csv col-n]
      (derive-column csv identity col-n))

-  ([csv f col-n]
-     (map #(conj % (f (nth % col-n))) csv)))
+  ([csv f & col-ns]
+     (->> csv
+          (map (fn [row]
+                 (conj row
+                       (apply-ns f row col-ns)))))))

 ;; alias to create a lightweight pattern matching style syntax for use
 ;; with mapc


IO working

IO working

--- src/clack/core.cljs
+++ src/clack/core.cljs
@@ -4,8 +4,18 @@

 (nodejs/enable-util-print!)

+(defn slurp-stdin []
+  ;(js/process.stdin.setEncoding "utf8")
+  ;(js/process.stdout.setEncoding "utf8")
+  (let [input (atom "")]
+    (js/process.stdin.on "readable" (fn []
+                                      (when-let [chunk (js/process.stdin.read)]
+                                        (swap! input #(str % chunk)))))
+    (js/process.stdin.on "end" (fn []
+                                 (print @input)))))
+
 (defn -main [& args]
-  (println "Hello world!"))
+  (slurp-stdin))

 (set! *main-cli-fn* -main)


wrap-file-info is deprecated. Use replacements

--- src/clojars/web.clj
+++ src/clojars/web.clj
@@ -28,10 +28,11 @@
              [route :refer [not-found]]]
             [ring.middleware
              [anti-forgery :refer [wrap-anti-forgery]]
-             [file-info :refer [wrap-file-info]]
+             [content-type :refer [wrap-content-type]]
              [flash :refer [wrap-flash]]
              [keyword-params :refer [wrap-keyword-params]]
              [multipart-params :refer [wrap-multipart-params]]
+             [not-modified :refer [wrap-not-modified]]
              [params :refer [wrap-params]]
              [resource :refer [wrap-resource]]
              [session :refer [wrap-session]]]))
@@ -132,7 +133,8 @@
        (wrap-flash)
        (wrap-secure-session)
        (wrap-resource "public")
-       (wrap-file-info)
+       (wrap-content-type)
+       (wrap-not-modified)
        (wrap-exceptions reporter))))

 (defn handler-optioned [{:keys [db error-reporter stats search]}]


Group by :batch-id

Group by :batch-id

--- src/eulalie/sqs.clj
+++ src/eulalie/sqs.clj
@@ -154,7 +154,7 @@
 (defn restructure-failed-batch [body]
   (let [ms (-> body
                (x/children :batch-result-error-entry)
-               (children-by-attr :id failed-batch-attr-renames))]
+               (children-by-attr :batch-id failed-batch-attr-renames))]
     (util/mapvals #(update-in % [:code] csk/->kebab-case-keyword) ms)))

 (defmethod restructure-response :delete-message-batch [_ body]


Do not specify :v8 and compress true.

Do not specify :v8 and compress true.

--- src/incise/core.clj
+++ src/incise/core.clj
@@ -23,8 +23,7 @@
   (conf/merge config)
   (let [out-dir (conf/get :out-dir)
         stefon-pre-opts {:cache-mode :production
-                         :compress false
-                         :engine :v8
+                         :compress true
                          :serving-root out-dir
                          :precompiles (conf/get :precompiles)}]
     (info "Clearing out" (str \" out-dir \"))


proof for the-lemma

proof for the-lemma

--- src/latte/quant.clj
+++ src/latte/quant.clj
@@ -93,7 +93,7 @@

   `(the T P u)` defines the unique inhabitant of type
  `T` satisfying the predicate `P`. This is provided
- thanks to the uniqueness proof `u`."
+ thanks to the uniqueness proof `u` (of type `(unique T P)`."
   [[T :type] [P (==> T :type)] [u (unique T P)]]
   T)


fix RegExp Closure errors

fix RegExp Closure errors

--- test/cljs/cljs/pprint_test.clj
+++ test/cljs/cljs/pprint_test.clj
@@ -5,8 +5,8 @@
   `(deftest ~name
      ~@(for [[x y] (partition 2 test-pairs)]
          `(cond
-            (= js/RegExp (type ~y)) (is (.exec ~y ~x))
-            (= js/String (type ~y)) (is (= ~x ~y))
+            (cljs.core/regexp? ~y) (is (.exec ~y ~x))
+            (cljs.core/string? ~y) (is (= ~x ~y))
             :else (is (= ~x ~y))))))

 (defmacro code-block


make test/mutation.clj run

make test/mutation.clj run

--- test/clojure/test/mutation.clj
+++ test/clojure/test/mutation.clj
@@ -49,30 +49,32 @@
            (is (= "No entity was found matching the key: A(\"B\")"
                   (.getMessage e)))))))

-(deftest ^:emap into-ds-1
-  (testing "into-ds 1: non-destructive save"
-    (let [em1 (ds/into-ds [:A/B] {:a 1})]
-      (try (ds/into-ds [:A/B] {:b 2})
-           (catch java.lang.RuntimeException e
-             (is (= "key already exists: [:A/B]"
-                    (.getMessage e))))))))
+;; FIXME:  keep into-ds! and into-ds internal?  only expose entity-map ctors?

-(deftest ^:emap into-ds!
-  (testing "into-ds!: destructive save"
-    (let [em1 (ds/into-ds! [:A/B] {:a 1 :b 2})
-          em1a (ds/get-ds [:A/B])]
-        (log/trace "em1:" (ds/print em1))
-        (log/trace "em1a:" (ds/print em1a))
-      (is (= (:a em1) 1))
-      (let [em2 (ds/into-ds! [:A/B] {:c 3})
-            em2b (ds/entity-map* [:A/B]) ;; co-constructor
-            em2a (ds/get-ds [:A/B])]     ;; getter
-        (log/trace "em2:" (ds/print em2))
-        (log/trace "em2a:" (ds/print em2a))
-        (is (= (:a em1) 1))             ; previously fetched emap unaffected
-        (is (= (:a em1a) 1))
-        (is (= (:b em2) nil))
-        (is (= (:a em2a) nil))
-        (is (= (:b em2a) nil))
-        (is (= (:c em2a) 3))
-      ))))
+;; (deftest ^:emap into-ds-1
+;;   (testing "into-ds 1: non-destructive save"
+;;     (let [em1 (ds/into-ds [:A/B] {:a 1})]
+;;       (try (ds/into-ds [:A/B] {:b 2})
+;;            (catch java.lang.RuntimeException e
+;;              (is (= "key already exists: [:A/B]"
+;;                     (.getMessage e))))))))
+
+;; (deftest ^:emap into-ds!
+;;   (testing "into-ds!: destructive save"
+;;     (let [em1 (ds/into-ds! [:A/B] {:a 1 :b 2})
+;;           em1a (ds/get-ds [:A/B])]
+;;         (log/trace "em1:" (ds/print em1))
+;;         (log/trace "em1a:" (ds/print em1a))
+;;       (is (= (:a em1) 1))
+;;       (let [em2 (ds/into-ds! [:A/B] {:c 3})
+;;             em2b (ds/entity-map* [:A/B]) ;; co-constructor
+;;             em2a (ds/get-ds [:A/B])]     ;; getter
+;;         (log/trace "em2:" (ds/print em2))
+;;         (log/trace "em2a:" (ds/print em2a))
+;;         (is (= (:a em1) 1))             ; previously fetched emap unaffected
+;;         (is (= (:a em1a) 1))
+;;         (is (= (:b em2) nil))
+;;         (is (= (:a em2a) nil))
+;;         (is (= (:b em2a) nil))
+;;         (is (= (:c em2a) 3))
+;;       ))))


[test/function-test] Fix requires.

[test/function-test] Fix requires.

--- test/cortex/function_test.cljc
+++ test/cortex/function_test.cljc
@@ -5,7 +5,7 @@
         [cljs.test :refer-macros [deftest is testing]]
         :clj
         [clojure.test :refer [deftest is testing]])
-    [cortex.core :refer [calc output forward backward input-gradient parameters gradient parameter-count]]
+    [cortex.core :refer [calc output forward backward input-gradient parameters gradient parameter-count calc-output]]
     [clojure.core.matrix :as m]
     #?(:cljs [thi.ng.ndarray.core :as nd])
     [cortex.layers :as layers]


oops revert changes to DB

oops revert changes to DB

--- src/metabase/db.clj
+++ src/metabase/db.clj
@@ -14,15 +14,9 @@
                    (:database-file app-defaults))))
 (log/info (str "Using H2 database file: " db-file))

-;; (defdb db (h2 {:db db-file
-;;                :naming {:keys str/lower-case
-;;                         :fields str/upper-case}}))
-
-(defdb db (postgres {:db "corvus"
-                     :port 15432
-                     :user "corvus"
-                     :password ""
-                     :host "localhost"}))
+(defdb db (h2 {:db db-file
+               :naming {:keys str/lower-case
+                        :fields str/upper-case}}))

 (defn migrate
   "Migrate the database :up or :down."


Fix ns spec failure for clj v1.10.0

Fix ns spec failure for clj v1.10.0

Fixes #14

--- src/octet/util.cljc
+++ src/octet/util.cljc
@@ -26,7 +26,7 @@
   (:require [clojure.string :as str :refer [join]]
             [octet.buffer :as bfr])

-  #?(:clj (:import [java.util.Arrays])))
+  #?(:clj (:import java.util.Arrays)))

 (defmacro defalias
   [sym sym2]


Improve primitive use

Improve primitive use

--- src/onyx/types.cljc
+++ src/onyx/types.cljc
@@ -7,11 +7,11 @@

 (defrecord Route [flow exclusions post-transformation action])

-(def message-id 0)
-(def barrier-id 1)
-(def heartbeat-id 2)
-(def ready-id 3)
-(def ready-reply-id 4)
+(def message-id (int 0))
+(def barrier-id (int 1))
+(def heartbeat-id (int 2))
+(def ready-id (int 3))
+(def ready-reply-id (int 4))

 (defn message [replica-version short-id payload]
   {:type message-id :replica-version replica-version :short-id short-id :payload payload})


Bin: log top-level errors.

Bin: log top-level errors.

--- src/reimann/bin.clj
+++ src/reimann/bin.clj
@@ -1,6 +1,10 @@
 (ns reimann.bin
   (:require reimann.config)
+  (:use clojure.tools.logging)
   (:gen-class))

 (defn -main [& argv]
-  (reimann.config/include (first argv)))
+  (try
+    (reimann.config/include (first argv))
+    (catch Exception e
+      (error e "Aborting"))))


Whitespace

Whitespace

--- test/staircase/test/webapp.clj
+++ test/staircase/test/webapp.clj
@@ -82,7 +82,6 @@
                                     :body (payload ident csrf)
                                     :content-type "application/json")
                            :response)]
-
           (is (= (:status response) 403)))))

     ))


cleanup

cleanup

--- src/babel/over.cljc
+++ src/babel/over.cljc
@@ -18,28 +18,6 @@
 (def ^:const mapfn pmap)

 (def ^:dynamic *extra-diagnostics* false)
-
-(defn check-vals [m1 m2 p1 p2]
-  (let [v1 (get-in m1 p1 :top)
-        v2 (get-in m2 p2 :top)
-        result
-        (cond (= :top v1)
-              false
-              (= :top v2)
-              false
-              (= :fail v1)
-              true
-              (= :top v2)
-              true
-              (and (map? m1)
-                   (map? m2))
-              (fail? (unifyc v1 v2))
-
-              true
-              (not (= v1 v2)))]
-    (if (= result true)
-      (log/debug (str "check-vals caught a fail: p1=" p1 "; p2=" p2 "; fail-path:" (fail-path m1 m2))))
-    result))

 (defn moreover-head [parent child & [morph]]
   (let [morph (if morph morph (fn [x] (str "(no morph function provided:" x)))]


working sentence generation.

working sentence generation.

--- src/markov/core.clj
+++ src/markov/core.clj
@@ -19,10 +19,6 @@

 (defn hash-ngram [ngram]
   {:root (take 2 ngram) :next-word (last ngram)})
-
-(defn make-ngram-hash [ngrams]
-  (let [])
-  )

 (defn gen-trigram [sentence]
   (gen-ngram sentence 3)
@@ -46,6 +42,42 @@
       (println "Get Corpus : Connected to 127.0.0.1 - " corpus-name)
       (cql/select session "corpus" (where [[= :corpus_name corpus-name]]) (allow-filtering))
      ))
+
+(defn generate-corpus-trigrams [corpus-name]
+  (let [corpus-results (get-corpus corpus-name)
+        document (map make-word-seq (map prep-sentence (map :sentence_text corpus-results)))
+        trigrams (mapcat gen-trigram document)
+        ])
+
+       (map hash-ngram trigrams)
+  )
+
+(defn generate-sentence [hashed-trigrams]
+  (let [starters (filter #(= "START" (first (:root %))) hashed-trigrams)
+        starter-idx (rand-int (count starters))
+        sentence-pieces (filter #(not= "START" (first (:root %))) hashed-trigrams)
+        starter (nth starters starter-idx)
+;        dummy (println starter)
+        root (second (:root starter))
+        sentence (seq [root (:next-word starter)])
+        ]
+    (loop [s sentence, prev-two sentence]
+      (let [next-choices (filter #(= prev-two (:root %)) sentence-pieces)
+            next-word (:next-word (nth next-choices (rand-int (count next-choices))))
+            next-prev (seq [(last s) next-word])
+;            dummy2 (println "Sent : " s)
+;            dummy3 (println "Prev : " prev-two)
+            ]
+
+        (if (= (last s) "END")
+          (str/join " "(butlast (flatten s)))
+          (recur (seq [s next-word]) next-prev)
+;          (recur (conj (seq next-word) s) next-prev)
+          )
+        )
+      )
+    )
+  )

 (defn -main
   "I don't do a whole lot ... yet."
@@ -65,6 +97,6 @@
       (def starters (filter #(= "START" (first (:root %))) hashed-trigrams))
       (def sentence-pieces (filter #(not= "START" (first (:root %))) hashed-trigrams))
 ;      (print-document start)
-      (print-document sentence-pieces)
+;      (print-document sentence-pieces)
      )


Let jline-based input also use repl-based input features by cascading the input methods.

--- src/cli4clj/cli.clj
+++ src/cli4clj/cli.clj
@@ -11,10 +11,13 @@
     :doc "cli4clj allows to create simple interactive command line interfaces for Clojure applications.
           For an example usage scenario please see the namespace cli4clj.example."}
   cli4clj.cli
-  (:use [clojure.main :only [repl skip-if-eol skip-whitespace]]
-        [clojure.string :only [blank? split]]
-        clj-assorted-utils.util)
-  (:import (jline.console ConsoleReader)))
+  (:use
+    [clojure.main :only [repl skip-if-eol skip-whitespace]]
+    [clojure.string :only [blank? split]]
+    clj-assorted-utils.util)
+  (:import
+    (java.io PushbackReader StringReader)
+    (jline.console ConsoleReader)))

 (defn cli-repl-print
   [arg]
@@ -24,17 +27,6 @@
 (defn cli-repl-prompt
   []
   (print "cli# "))
-
-(defn create-jline-read-fn
-  []
-  (let [rdr (doto (ConsoleReader.))]
-    (fn [request-prompt request-exit]
-      (let [in-line (.readLine rdr)]
-        (if (not (blank? in-line))
-          (reduce (fn [v in-part] (conj v (read-string in-part)))
-                  []
-                  (split in-line #"\s")))))))
-

 (defn create-repl-read-fn
   []
@@ -55,6 +47,14 @@
               (if (= :line-start (skip-whitespace *in*))
                 (conj v input)
                 (recur (conj v input)))))))))
+
+(defn create-jline-read-fn
+  []
+  (let [in-rdr (doto (ConsoleReader.))
+        rdr-fn (create-repl-read-fn)]
+    (fn [request-prompt request-exit]
+      (binding [*in* (PushbackReader. (StringReader. (str (.readLine in-rdr) "\n")))]
+        (rdr-fn request-prompt request-exit)))))

 (defn resolve-cmd-alias
   [input-cmd cmds]


fuck, typo

fuck, typo

--- src/odr/queries.clj
+++ src/odr/queries.clj
@@ -16,7 +16,7 @@
 (defqueries "odr/queries.sql" {:connection (db-spec)})

 (defn parse-party-line []
-  (let [pl (partyline)]
+  (let [pl (party-line)]
     (zipmap (map (fn [x] [(:id_hlasovani x) (:pohlavi x)])
                  pl)
             (map :vysledek pl))))


Fastened lectic-<_i

Fastened lectic-<_i

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/base.clj
+++ src/conexp/base.clj
@@ -65,8 +65,13 @@
   A and B have to be sets."
   [G i A B]
   (and (contains? B i) (not (contains? A i)) ; A and B will always be sets
-       (forall [j (subelts G i)]
-         (<=> (contains? B j) (contains? A j)))))
+       (loop [elements G]
+         (let [j (first elements)]
+           (if (= j i)
+             true
+             (if (identical? (contains? B j) (contains? A j))
+               (recur (rest elements))
+               false))))))

 (defn lectic-<
   "Implements lectic ordering. The basic order is given by the ordering of G
@@ -78,11 +83,9 @@
   "Computes next closed set as with next-closed-set, which is in the
   family $\\mathcal{F}$ of all closed sets satisfing
   predicate. predicate has to satisfy the condition
-  \\[
-     A \\in \\mathcal{F} \text{ and } i \\in G
-     \\implies
-     \\mathrm{clop}(A \\cap \\set{1, \\ldots, i-1}) \\in \\mathcal{F}.
-  \\]"
+
+    A ∈ F and i ∈ G ==> clop(A ∪ {1, …, i-1}) ∈ F.
+  "
   [predicate G clop A]
   (loop [i-s (reverse G),
          A   (set A)]


Little more work in conexp.util

Little more work in conexp.util

Signed-off-by: Daniel Borchmann <25857343a15bf1edafebc2912e82ecf775c585c1@mailbox.tu-dresden.de>

--- src/conexp/util.clj
+++ src/conexp/util.clj
@@ -2,6 +2,20 @@
   (:use clojure.contrib.profile
 	[clojure.contrib.math :only (round)])
   (:import javax.swing.JOptionPane))
+
+
+;;; Namespace documentation
+
+(defmacro update-ns-meta!
+  "Updates meta hash of given namespace with given description."
+  [ns & key-value-description]
+  `(alter-meta! (find-ns '~ns)
+		(fn [meta-hash#]
+		  (merge meta-hash# ~(apply hash-map key-value-description)))))
+
+(update-ns-meta! conexp.util
+  :doc "Loose collection of some useful functions and macros for conexp.")
+

 ;;; Compilation

@@ -16,10 +30,11 @@
   (compile 'conexp.gui.repl)
   nil)

+
 ;;; Types

-; work over this and make it more flexible
-; we may need our own hierachy?
+;; work over this and make it more flexible
+;; we may need our own hierachy?

 (defn math-type
   "Dispatch function for multimethods. Identifies sets and sequences
@@ -33,6 +48,7 @@
 	(sequential? thing)) ::set
     :else                    ::other))

+
 ;;; Technical Helpers

 (defn ensure-length
@@ -94,7 +110,9 @@
   [& strings]
   (throw (IllegalArgumentException. #^String (apply str strings))))

-(defmacro with-profiled-fns [fns & body]
+(defmacro with-profiled-fns
+  "Runs code in body with all given functions being profiled."
+  [fns & body]
   `(binding ~(vec (apply concat
 			 (for [fn (distinct fns)]
 			   `[~fn (let [orig-fn# ~fn]
@@ -105,7 +123,9 @@
        (if (not (empty? data#))
 	 (print-summary (summarize data#))))))

-(defmacro memo-fn [name args & body]
+(defmacro memo-fn
+  "Defines memoized, anonymous function."
+  [name args & body]
   `(let [cache# (ref {})]
      (fn ~name ~args
        (if (contains? @cache# ~args)
@@ -115,7 +135,9 @@
 	    (alter cache# assoc ~args rslt#))
 	   rslt#)))))

-(defmacro recur-sequence [& things]
+(defmacro recur-sequence
+  "Define a recursive sequence in a math-like notation."
+  [& things]
   (let [initials (vec (butlast things))
 	recur-fn (last things)]
     `(let [initials# (lazy-seq ~initials)]
@@ -126,7 +148,9 @@
 		      (cons new-val# (step# (inc n#) (concat (rest old-vals#) (list new-val#)))))))
 		~(count initials) initials#)))))

-(defmacro with-recur-seqs [seq-definitions & body]
+(defmacro with-recur-seqs
+  "Allow simple definitions of recursive sequences."
+  [seq-definitions & body]
   (let [seq-names (take-nth 2 seq-definitions)
 	seq-defs  (take-nth 2 (rest seq-definitions))]
     `(let [~@(reduce concat (map (fn [seq-name] `(~seq-name (ref []))) seq-names))]
@@ -154,6 +178,7 @@
 		   (lazy-seq
 		     (cons (vec rest) (runner (next rest))))))]
     (runner sqn)))
+

 ;;; Math

@@ -219,17 +244,13 @@
 	  {}
 	  keys))

-(defmacro update-ns-meta!
-  "Updates meta hash of given namespace with given description."
-  [ns & key-value-description]
-  `(alter-meta! (find-ns '~ns)
-		(fn [meta-hash#]
-		  (merge meta-hash# ~(apply hash-map key-value-description)))))
-
 (defn hash-from-attributes
   "Computes a hash value from the values returned from funs applied to this."
   [this funs]
   (reduce bit-xor 0 (map #(%1 this) funs)))
+
+
+;;; Swings

 (defn get-root-cause
   "Returns original message of first exception causing the given one."


Add slamhound, nrepl/pretty-middleware

Add slamhound, nrepl/pretty-middleware

* Slamhound for fixin missing imports/require and optimizing these
* aviso middleware for pretty-printing exceptions in repl

--- .lein/profiles.clj
+++ .lein/profiles.clj
@@ -9,13 +9,17 @@
                        [ritz/ritz-nrepl-middleware "0.7.0"]
                        [night-vision "0.1.0-SNAPSHOT"] ;; print input/output of each call in a ns; see (night-vision.goggles/introspect-ns! '<your ns>)
                        [leiningen "2.3.4"] ;; Vinyasa needs this, must match my lein version
+                       [alembic "0.2.1"]   ;; reload new deps from project.clj
+                       [slamhound "1.5.2"] ;; optimize and add missing requires/imports in .clj files - see aliases below or editor-specific plugins or run from repl
+                       [io.aviso/pretty "0.1.10"] ;; nrepl/pretty-middleware for exceptions
+                       ;; from REPL: (slam.hound/-main "src/my/namespace.clj")
                        ]
-        ;; "Copy" the given function to clojure.core (and thus all namespaces), prefixed with > => (>doc ..)
+
         :injections [(require 'vinyasa.inject) ;; TODO check also vinyasa/pull, lein, reimport
                      (require 'alex-and-georges.debug-repl)
                      (require 'com.georgejahad.difform)
                      (require 'clj-ns-browser.sdoc)
-                     (vinyasa.inject/inject 'clojure.core '>
+                     (vinyasa.inject/inject 'clojure.core '> ;; "Copy" the given function to clojure.core (and thus all namespaces), prefixed with > => (>doc ..)
                        '[[clojure.repl doc source]
                          [clojure.pprint pprint pp]
                          [vinyasa.pull pull]
@@ -38,13 +42,18 @@
                   [lein-alembic "0.1.0"]     ; make alembic available -> reload prj deps w/o restarting repl: (alembic.still/load-project)
                   [lein-clojuredocs "1.0.2"] ; Create clojuredocs-style doc
                   ;;[quickie "0.2.6"] ; autotest for clojure.test
-                  [com.jakemccrary/lein-test-refresh "0.3.4"] ;; autotest: lein test-refresh :growl
+                  [com.jakemccrary/lein-test-refresh "0.3.4"] ;; autotest: lein test-refresh :growl ; weak results reporting :-(
                   [lein-light "0.0.44"] ; LightTable: `lein light` in a prj
-                  ]}
-       :repl-options {:nrepl-middleware
-                       [
-                        ;inspector.middleware/wrap-inspect
-                        ritz.nrepl.middleware.javadoc/wrap-javadoc
-                        ritz.nrepl.middleware.apropos/wrap-apropos
-                        ritz.nrepl.middleware.simple-complete/wrap-simple-complete]}
- }
+                  ]
+        :aliases {
+                  "slamhound" ["run" "-m" "slam.hound"] ;; => lein slamhound <file or dir>
+                  }
+        :repl-options {:nrepl-middleware
+                      [
+                       ;inspector.middleware/wrap-inspect
+                       ritz.nrepl.middleware.javadoc/wrap-javadoc
+                       ritz.nrepl.middleware.apropos/wrap-apropos
+                       ritz.nrepl.middleware.simple-complete/wrap-simple-complete
+                       io.aviso.nrepl/pretty-middleware ;; pretty-print exceptions in repl
+                       ]}
+ }}


Set shouldComponentUpdate as default.

Set shouldComponentUpdate as default.

--- src/pump/utils.cljs
+++ src/pump/utils.cljs
@@ -18,9 +18,17 @@
                          (aset state "state" (get-initial-state this))
                          state))})

+(defn should-component-update
+  [next-props next-state]
+  (this-as
+   this
+   (not (and (= next-props (.-props this))
+             (= (.-state next-state) (-> this .-state .-state))))))
+
 (defn wrap-functions
   [{:keys [render] :as props-map}]
-  (into {:getInitialState #(js/Object.)}
+  (into {:getInitialState #(js/Object.)
+         :shouldComponentUpdate should-component-update}
         (for [[k fn] props-map
               :let [special (special-wrappers k)]]
           [k (if (nil? special)


Cleanups.

Cleanups.

--- s3/src/s3/blog.clj
+++ s3/src/s3/blog.clj
@@ -16,9 +16,6 @@
 (defn _id-to-id [mongo-object]
   (let [id (str (:_id mongo-object))]
     (-> mongo-object (dissoc :_id) (assoc :id id))))
-
-(defn create-draft [user]
-  (_id-to-id (mc/insert-and-return *db* BLOG {:draft true :user user})))

 (defn own? [user dbo]
   (= user (:user dbo)))
@@ -58,18 +55,21 @@
                :time #(-> % parse-duration int)}
    :validation [:user #(-> % :draft nil? not)]})

-(defn find-dbo [id]
+(defn find-blog-object [id]
   (mc/find-one-as-map *db* BLOG {:_id (ObjectId. id)}))

+(defn create-draft [user]
+  (_id-to-id (mc/insert-and-return *db* BLOG {:draft true :user user})))
+
 (defn create [user params]
-  (let [blog (assoc params :user user)
-        id (:id blog)
-        dbo (find-dbo id)]
-    (if (and (not= nil dbo) (own? user dbo))
-      (-> blog
+  (let [new-blog (assoc params :user user)
+        id (:id new-blog)
+        db-object (find-blog-object id)]
+    (if (and (not= nil db-object) (own? user db-object))
+      (-> new-blog
           (transform-using to-db-transform)
-          (insert-and-return dbo))
-      (error "Db object deleted or not own. Refusing to create" user blog dbo))))
+          (insert-and-return db-object))
+      (error "Db object deleted or not own. Refusing to create" user new-blog db-object))))

 (defn get [id]
-  (from-db-to-user (find-dbo id)))+  (from-db-to-user (find-blog-object id)))


spacing between functionparts

spacing between functionparts

--- src/funcgo/core.clj
+++ src/funcgo/core.clj
@@ -31,7 +31,7 @@
 functiondecl   = <'func'> _ identifier _ Function
 functionlit    = <'func'> _ Function
 <Function>     = functionpart | functionparts
-functionparts  = functionpart functionpart+
+functionparts  = functionpart _ functionpart { _ functionpart }
 functionpart   = <'('> _ parameters _ <')'> _ <'{'> _ Expression _ <'}'>
 parameters     = ( identifier [ <','> _ identifier ]  )? ( _ varadic)?
 varadic        = identifier _ <'...'>


fix mistake

fix mistake

--- src/survey/core.clj
+++ src/survey/core.clj
@@ -16,8 +16,8 @@
 (def db-spec {:classname "org.postgresql.Driver"
               :subprotocol "postgresql"
               :subname "//localhost:5432/survey"
-              :user "sulmanen"
-              :password "pftvppeh"})
+              :user "pepsi"
+              :password "pepsi"})

 ;;liquibase
 (def ct-change1 (ch/create-table :answers


fix failed removal workflow-id

fix failed removal workflow-id

--- src-cljs/frontend/controllers/navigation.cljs
+++ src-cljs/frontend/controllers/navigation.cljs
@@ -136,7 +136,7 @@
   (set-page-title! "Build State"))

 (defn- add-crumbs [state {:keys [vcs_type project-name build-num org repo tab container-id action-id]}]
-  (let [{:keys [workflow-id]} (get-in state state/navigation-data-path) (workflow-id state)
+  (let [{:keys [workflow-id]} (get-in state state/navigation-data-path)
         crumbs (if workflow-id
                  [{:type :workflows-dashboard}
                   {:type :org :username org :vcs_type vcs_type}


Päivitetään depsut

Päivitetään depsut

--- mtg-pairings-server/project.clj
+++ mtg-pairings-server/project.clj
@@ -5,32 +5,32 @@
                  [org.clojure/core.async "0.4.474"]
                  [reagent "0.8.1" :exclusions [cljsjs/react]]
                  [reagent-utils "0.3.1"]
-                 [ring "1.6.3"]
+                 [ring "1.7.1"]
                  [ring/ring-defaults "0.3.2"]
                  [compojure "1.6.1"]
                  [hiccup "1.0.5"]
                  [yogthos/config "1.1.1"]
-                 [org.clojure/clojurescript "1.10.339"]
+                 [org.clojure/clojurescript "1.10.312"]
                  [secretary "1.2.3"]
                  [venantius/accountant "0.2.4"
                   :exclusions [org.clojure/tools.reader]]
                  [org.clojure/core.cache "0.7.1"]
                  [http-kit "2.3.0"]
-                 [org.clojure/tools.reader "1.2.2"]
-                 [clj-time "0.14.4"]
+                 [org.clojure/tools.reader "1.3.2"]
+                 [clj-time "0.15.1"]
                  [com.andrewmcveigh/cljs-time "0.5.2"]
                  [korma "0.4.3"]
-                 [mount "0.1.11"]
-                 [org.postgresql/postgresql "42.2.2"]
+                 [mount "0.1.14"]
+                 [org.postgresql/postgresql "42.2.5"]
                  [metosin/compojure-api "1.1.12"]
                  [ring.middleware.jsonp "0.1.6"]
-                 [com.taoensso/sente "1.12.0" :exclusions [com.taoensso/encore]]
+                 [com.taoensso/sente "1.13.1" :exclusions [com.taoensso/encore]]
                  [com.taoensso/timbre "4.10.0"]
-                 [com.cognitect/transit-clj "0.8.309"]
+                 [com.cognitect/transit-clj "0.8.313"]
                  [com.cognitect/transit-cljs "0.8.256"]
-                 [re-frame "0.10.5" :exclusions [cljsjs/react]]
-                 [cljsjs/react "16.4.0-0"]
-                 [cljsjs/react-transition-group "2.3.1-0"]]
+                 [re-frame "0.10.6" :exclusions [cljsjs/react]]
+                 [cljsjs/react "16.6.0-0"]
+                 [cljsjs/react-transition-group "2.4.0-0"]]
   :plugins [[lein-environ "1.1.0" :exclusions [org.clojure/clojure]]
             [lein-cljsbuild "1.1.7"]
             [lein-asset-minifier "0.3.2"]]
@@ -91,12 +91,12 @@
                        :dependencies [[org.clojure/tools.namespace "0.2.11"]
                                       [binaryage/devtools "0.9.10"]
                                       [ring/ring-mock "0.3.2"]
-                                      [ring/ring-devel "1.6.3"]
-                                      [prone "1.6.0"]
-                                      [figwheel-sidecar "0.5.16"]
+                                      [ring/ring-devel "1.7.1"]
+                                      [prone "1.6.1"]
+                                      [figwheel-sidecar "0.5.17"]
                                       [org.clojure/tools.nrepl "0.2.13"]
                                       [com.cemerick/piggieback "0.2.2"]
-                                      [pjstadig/humane-test-output "0.8.3"]
+                                      [pjstadig/humane-test-output "0.9.0"]
                                       [day8.re-frame/re-frame-10x "0.3.3-react16"]]}
              :uberjar {:main         mtg-pairings-server.main
                        :aot          :all


fixed edit save redirect

fixed edit save redirect

--- src/cljs/swarmpit/component/service/edit.cljs
+++ src/cljs/swarmpit/component/service/edit.cljs
@@ -156,7 +156,7 @@
    (form/section "Deployment")
    (deployment/form)])

-(rum/defc form-edit < rum/reactive [params service]
+(rum/defc form-edit < rum/reactive [id service]
   [:div
    [:div.form-panel
     [:div.form-panel-left
@@ -165,14 +165,14 @@
     [:div.form-panel-right
      (comp/mui
        (comp/raised-button
-         {:onTouchTap #(update-service-handler params)
+         {:onTouchTap #(update-service-handler id)
           :label      "Save"
           :disabled   (not (rum/react resources/isValid))
           :primary    true}))
      [:span.form-panel-delimiter]
      (comp/mui
        (comp/raised-button
-         {:href  (routes/path-for-frontend :service-info params)
+         {:href  (routes/path-for-frontend :service-info {:id id})
           :label "Back"}))]]
    [:div.form-service-edit
     (form-settings)
@@ -187,8 +187,8 @@
     (form-deployment)]])

 (rum/defc form < rum/reactive
-                 mixin-init-state [params]
+                 mixin-init-state [{:keys [id]}]
   (let [service (state/react cursor)]
     (progress/form
       (nil? service)
-      (form-edit params service))))+      (form-edit id service))))


Improved path constructor on storages module.

--- vendor/storages/core.clj
+++ vendor/storages/core.clj
@@ -40,10 +40,10 @@

 (defn path
   "Create path from string or more than one string."
-  [fst & more]
-  (if (seq more)
-    (pt/-path (cons fst more))
-    (pt/-path fst)))
+  ([fst]
+   (pt/-path fst))
+  ([fst & more]
+   (pt/-path (cons fst more))))

 (defn public-url
   [storage path]


adding part 2

adding part 2

--- 2016/day-10/src/day_10/core.clj
+++ 2016/day-10/src/day_10/core.clj
@@ -88,8 +88,7 @@
         (map parse-cmd)
         cycle
         (reductions #(%2 %1) initial-board)
-        (filter (bot-has chips))
-        (take 1))))
+        (map println))))

 (defn -main
   "I don't do a whole lot ... yet."


lein-release plugin: bumped version from 0.4.6 to 0.4.7-SNAPSHOT for next development cycle

--- re_view/project.clj
+++ re_view/project.clj
@@ -1,4 +1,4 @@
-(defproject re-view "0.4.6"
+(defproject re-view "0.4.7-SNAPSHOT"
   :description "ClojureScript React Library"
   :url "https://www.github.com/braintripping/re-view/tree/master/re_view"
   :license {:name "Eclipse Public License"


Add license info to synth-designs file.

Add license info to synth-designs file.

--- etc/synthdefs/synth-designs.clj
+++ etc/synthdefs/synth-designs.clj
@@ -1,3 +1,20 @@
+;;--
+;; This file is part of Sonic Pi: http://sonic-pi.net
+;; Full project source: https://github.com/samaaron/sonic-pi
+;; License: https://github.com/samaaron/sonic-pi/blob/master/LICENSE.md
+;;
+;; Copyright 2013, 2014 by Sam Aaron (http://sam.aaron.name).
+;; All rights reserved.
+;;
+;; Permission is granted for use, copying, modification, distribution,
+;; and distribution of modified versions of this work as long as this
+;; notice is included.
+;;++
+
+;; This file uses Overtone to compile the synths from Clojure to
+;; SuperCollider compatible binary files. Overtone is Sonic Pi's big
+;; brother. See: http://overtone.github.io
+
 (ns sp
   (:use [overtone.live])
   (:require [clojure.string :as str]))


make aside menu closed by default

make aside menu closed by default

--- src-cljs/frontend/state.cljs
+++ src-cljs/frontend/state.cljs
@@ -13,7 +13,7 @@
    :settings        {:browser-settings {:show-grid?  true
                                         :night-mode? true
                                         :current-tool :rect
-                                        :aside-menu-opened true
+                                        :aside-menu-opened false
                                         :chat-mobile-opened true}}
    :current-user    nil
    :instrumentation []


(maint) command.constants: simplify version handling

Since there are few values, just provide literals for the version
sets.  Omit "get" when a nil missing value is no worse.

--- src/puppetlabs/puppetdb/command/constants.clj
+++ src/puppetlabs/puppetdb/command/constants.clj
@@ -12,23 +12,20 @@

 (def command-keys (set/map-invert command-names))

-(defn- version-range [min-version max-version]
-  (set (range min-version (inc max-version))))
+(def supported-command-versions
+  {"configure expiration" #{1}
+   "replace facts" #{2 3 4 5}
+   "replace catalog" #{4 5 6 7 8 9}
+   "replace catalog inputs" #{1}
+   "store report" #{3 4 5 6 7 8}
+   "deactivate node" #{1 2 3}})

-(def supported-command-versions
-  {"configure expiration" (version-range 1 1)
-   "replace facts" (version-range 2 5)
-   "replace catalog" (version-range 4 9)
-   "replace catalog inputs" (version-range 1 1)
-   "store report" (version-range 3 8)
-   "deactivate node" (version-range 1 3)})
-
-(def latest-catalog-version (apply max (get supported-command-versions "replace catalog")))
-(def latest-report-version (apply max (get supported-command-versions "store report")))
-(def latest-facts-version (apply max (get supported-command-versions "replace facts")))
-(def latest-configure-expiration-version (apply max (get supported-command-versions "configure expiration")))
-(def latest-catalog-inputs-version (apply max (get supported-command-versions "replace catalog inputs")))
-(def latest-deactivate-node-version (apply max (get supported-command-versions "deactivate node")))
+(def latest-catalog-version (apply max (supported-command-versions "replace catalog")))
+(def latest-report-version (apply max (supported-command-versions "store report")))
+(def latest-facts-version (apply max (supported-command-versions "replace facts")))
+(def latest-configure-expiration-version (apply max (supported-command-versions "configure expiration")))
+(def latest-catalog-inputs-version (apply max (supported-command-versions "replace catalog inputs")))
+(def latest-deactivate-node-version (apply max (supported-command-versions "deactivate node")))

 (def latest-command-versions
   {:replace_catalog latest-catalog-version


Removed no longer used ultimate-ttt.interface.state-handler

re-frame took its job

--- src/ultimate_ttt/interface/state_handler.cljs
+++ src/ultimate_ttt/interface/state_handler.cljs
@@ -1,35 +0,0 @@
-(ns ultimate-ttt.interface.state-handler
-  (:require [reagent.core :as reagent :refer [atom]]
-            [ultimate-ttt.game.board :as board-helper]))
-
-#_(
-(defn- choose-next-owner []
-  (let [current-owner (:current-owner @app-state)]
-    (if (= current-owner 1) 2 1)))
-
-(defn- change-current-owner []
-  (swap! app-state assoc :current-owner (choose-next-owner)))
-
-(defn- change-cell-owner [index board-cursor]
-  (let [board-record (:board @board-cursor)
-        coordinates (board-helper/calculate-coordinates board-record index)
-        current-owner (:current-owner @app-state)
-        new-board (board-helper/set-cell board-record (first coordinates) (second coordinates) current-owner)]
-    (swap! board-cursor assoc :board new-board)))
-
-(defn- set-active-board [index]
-  (swap! app-state assoc :active-board (get-in @app-state [:boards index :board])))
-
-(defn is-active? [board]
-  (let [active-board (:active-board @app-state)]
-    (or
-      (nil? active-board)
-      (= board active-board))))
-
-(defn on-cell-click [index board-cursor]
-  (let [board-record (:board @board-cursor)]
-    (when (is-active? board-record)
-      (change-cell-owner index board-cursor)
-      (change-current-owner)
-      (set-active-board index))))
-)


Use same color for whole feature

Use same color for whole feature

--- src/archi/core.clj
+++ src/archi/core.clj
@@ -64,7 +64,7 @@
   (when (described-path? path) (first path)))

 (defn make-feature-edge [feature path n1 n2]
-  (let [color (random-color)
+  (let [color (:color feature)
         short-desc (feature-short-desc feature)
         full-desc (feature-full-desc feature)
         path-desc (path-desc path)
@@ -77,11 +77,13 @@
                         :tooltip full-desc}]))

 (defn feature->edges [feature]
-  (apply concat (for [path (:paths feature)]
-                  (let [without-desc-path (if (described-path? path) (rest path) path)]
-                    (map (partial make-feature-edge feature path)
-                         without-desc-path
-                         (rest without-desc-path))))))
+  (let [color (random-color)
+        feature (assoc feature :color color)]
+    (apply concat (for [path (:paths feature)]
+                    (let [without-desc-path (if (described-path? path) (rest path) path)]
+                      (map (partial make-feature-edge feature path)
+                           without-desc-path
+                           (rest without-desc-path)))))))

 (defn make-scripts [edges]


fix: lein plugin parentheses after PR merge

--- provider/pact-jvm-provider-lein/src/main/clojure/au/com/dius/pact/provider/lein/verify_provider.clj
+++ provider/pact-jvm-provider-lein/src/main/clojure/au/com/dius/pact/provider/lein/verify_provider.clj
@@ -72,7 +72,7 @@
     (if (not-empty failures)
       (do
         (.displayFailures verifier (into {} failures))
-        (throw (ex-info (str "There were " (count failures) " pact failures")) {})))))
+        (throw (ex-info (str "There were " (count failures) " pact failures") {}))))))

 (defn verify [verifier pact-info]
   (verify-providers verifier (:service-providers pact-info)))


Add better docstrings.

Add better docstrings.

--- src/bide/core.cljs
+++ src/bide/core.cljs
@@ -32,6 +32,7 @@
 ;; --- Low Level Routes API

 (defn ^boolean router?
+  "Check if the `v` is a Router instance."
   [v]
   (rtr/isRouter v))

@@ -46,13 +47,15 @@
   (rtr/insert router path name))

 (defn match
+  "Try to match a path to a specific route in the router, returns `nil`
+  if the no match is found."
   [router path]
   (let [[name params] (into [] (rtr/match router path))]
     (when name
       [name (js->clj params :keywordize-keys true)])))

 (defn build
-  "Build a router with the provided routes."
+  "A helper for compile a vector of routes in a router instance."
   [routes]
   {:pre [(vector? routes)]}
   (reduce (fn [router [path name]]


Add "Sorting a vector of length 1 returns the same value" test

--- test/com/nomistech/clojure_the_language/c_800_libraries/s_105_generative_testing/midje_gen_test.clj
+++ test/com/nomistech/clojure_the_language/c_800_libraries/s_105_generative_testing/midje_gen_test.clj
@@ -54,3 +54,10 @@
       (fact (< (first s) (last s))
         => truthy)))
   )
+
+;;;; ___________________________________________________________________________
+;;;; More examples
+
+(for-all "Sorting a vector of length 0 or 1 returns the same value"
+    [v (gen/vector gen/int 0 1)]
+  (fact (sort v) => v))


Remove unnecessary call to (ctx/get-current)

Since the 1-arity return is defined to call the 2-arity
return, passing (ctx/get-current) as the first argument,
the (ctx/get-current) call here is unnecessary.

--- src/cats/core.cljc
+++ src/cats/core.cljc
@@ -728,7 +728,7 @@
   "
   ([f z xs]
    (if (empty? xs)
-     (return (ctx/get-current) z)
+     (return z)
      (let [[h & t] xs]
        (mlet [z' (f z h)]
          (if (empty? t)


Trying to make animations more sensible with sub-steps.

--- src/cbfg/core.cljs
+++ src/cbfg/core.cljs
@@ -266,17 +266,26 @@
       (when (< @event-delay 0) (<! step-ch))
       (let [[actx event] (<! event-ch)
             [verb step & args] event
+            vis-last @vis
+            vis-positions (atom {})
             vis-event-handler (get (get vis-event-handlers verb) step)
-            positions (atom {})
             deltas (vis-event-handler vis actx args)
             actx-ch-ch-infos (group-by #(:first-taker-actx (second %)) (:chs @vis))]
+        (set-el-innerHTML "event"
+                          (str num-events ": " (last actx) " " verb " " step " " args))
+        (when (and (<= @event-delay 1000) (not-empty deltas))
+          (set-el-innerHTML "vis-html"
+                            (apply str (flatten (vis-html-actx vis-last @root-actx vis-positions
+                                                               actx-ch-ch-infos))))
+          (set-el-innerHTML "vis-svg"
+                            (apply str (flatten (vis-svg-actxs vis-last @vis-positions deltas))))
+          (when (> @event-delay 0) (<! (timeout @event-delay)))
+          (when (< @event-delay 0) (<! step-ch)))
         (set-el-innerHTML "vis-html"
-                          (apply str (flatten (vis-html-actx @vis @root-actx positions
+                          (apply str (flatten (vis-html-actx @vis @root-actx vis-positions
                                                              actx-ch-ch-infos))))
         (set-el-innerHTML "vis-svg"
-                          (apply str (flatten (vis-svg-actxs @vis @positions deltas))))
-        (set-el-innerHTML "event"
-                          (str num-events ": " (last actx) " " verb " " step " " args))
+                          (apply str (flatten (vis-svg-actxs @vis @vis-positions nil))))
         (recur (inc num-events))))
     (ago w-actx w
          (reset! root-actx w-actx)


Fix tests

Fix tests

--- test/day8/re_frame/trace/metamorphic_test.clj
+++ test/day8/re_frame/trace/metamorphic_test.clj
@@ -67,74 +67,3 @@
       (is (= (m/beginning-id m6) 50))
       (is (= (m/ending-id m6) 181))
       (is (= (:operation (m/matched-event m6)) :acme.myapp.events/success-bootstrap))))
-
-(def sub-state '{:reaction-state {"rx48" {:subscription [:todos], :value ({:id 3, :title "def", :done false})}, "rx47" {:subscription [:sorted-todos], :value {3 {:id 3, :title "def", :done false}}, :previous-value {3 {:id 3, :title "def", :done false}}, :run? true, :order [:sub/run]}, "rx52" {:subscription [:visible-todos], :value ({:id 3, :title "def", :done false})}, "rx51" {:subscription [:showing], :value :all, :previous-value :all, :run? true, :order [:sub/run]}, "rx53" {:subscription [:all-complete?], :value false}, "rx56" {:subscription [:footer-counts], :value [1 0]}, "rx57" {:subscription [:completed-count], :value 0}}
-                 :last-matched-id 0})
-
-(def filtered-traces '({:id 91, :operation :initialise-db, :op-type :event, :tags {:event [:initialise-db], :app-db-before {:todos {3 {:id 3, :title "def", :done false}}, :showing :all}, :app-db-after {:todos {3 {:id 3, :title "def", :done false}}, :showing :all}}, :child-of nil, :start 647756.055, :duration 0.8649999999906868, :end 647756.93} {:id 92, :operation :sorted-todos, :op-type :sub/run, :tags {:query-v [:sorted-todos], :reaction "rx47", :input-signals ("ra24"), :value {3 {:id 3, :title "def", :done false}}}, :child-of nil, :start 647757.0300000001, :duration 0.08999999996740371, :end 647757.1250000001} {:id 93, :operation :showing, :op-type :sub/run, :tags {:query-v [:showing], :reaction "rx51", :input-signals ("ra24"), :value :all}, :child-of nil, :start 647757.16, :duration 0.05500000005122274, :end 647757.2150000001} {:id 94, :operation "todomvc.views.todo_app", :op-type :render, :tags {:component-path "todomvc.views.todo_app", :reaction "rx49", :input-signals ("rx48")}, :child-of nil, :start 647757.6200000001, :duration 0.2999999999301508, :end 647757.925} {:id 95, :operation :todos, :op-type :sub/create, :tags {:query-v [:todos], :cached? true, :reaction "rx48"}, :child-of 94, :start 647757.655, :duration 0.07499999995343387, :end 647757.735} {:id 96, :operation "todomvc.views.task_entry", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.task_entry", :reaction nil, :input-signals nil}, :child-of nil, :start 647758.14, :duration 0.1150000001071021, :end 647758.26} {:id 97, :operation "todomvc.views.todo_input", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.task_entry >  > todomvc.views.todo_input", :reaction "rx50", :input-signals ("ra59")}, :child-of nil, :start 647758.4750000001, :duration 0.24999999988358468, :end 647758.725} {:id 98, :operation "ReagentInput", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.task_entry >  > todomvc.views.todo_input > ReagentInput", :reaction nil, :input-signals nil}, :child-of nil, :start 647758.87, :duration 0.11000000010244548, :end 647758.9850000001} {:id 99, :operation "todomvc.views.task_list", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.task_list", :reaction "rx54", :input-signals ("rx52" "rx53")}, :child-of nil, :start 647759.36, :duration 0.4050000000279397, :end 647759.77} {:id 100, :operation :visible-todos, :op-type :sub/create, :tags {:query-v [:visible-todos], :cached? true, :reaction "rx52"}, :child-of 99, :start 647759.39, :duration 0.06499999994412065, :end 647759.4600000001} {:id 101, :operation :all-complete?, :op-type :sub/create, :tags {:query-v [:all-complete?], :cached? true, :reaction "rx53"}, :child-of 99, :start 647759.4800000001, :duration 0.044999999925494194, :end 647759.525} {:id 102, :operation "ReagentInput", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.task_list >  > ReagentInput", :reaction nil, :input-signals nil}, :child-of nil, :start 647759.95, :duration 0.06500000006053597, :end 647760.015} {:id 103, :operation "todomvc.views.todo_item", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.task_list >  >  > todomvc.views.todo_item", :reaction "rx55", :input-signals ("ra60" "ra60")}, :child-of nil, :start 647760.255, :duration 0.2500000001164153, :end 647760.51} {:id 104, :operation "ReagentInput", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.task_list >  >  > todomvc.views.todo_item >  >  > ReagentInput", :reaction nil, :input-signals nil}, :child-of nil, :start 647760.8550000001, :duration 0.08999999996740371, :end 647760.9450000001} {:id 105, :operation "todomvc.views.footer_controls", :op-type :render, :tags {:component-path "todomvc.views.todo_app >  >  > todomvc.views.footer_controls", :reaction "rx58", :input-signals ("rx56" "rx51")}, :child-of nil, :start 647761.39, :duration 0.8050000000512227, :end 647762.2} {:id 106, :operation :footer-counts, :op-type :sub/create, :tags {:query-v [:footer-counts], :cached? true, :reaction "rx56"}, :child-of 105, :start 647761.43, :duration 0.2850000000325963, :end 647761.7200000001} {:id 107, :operation :showing, :op-type :sub/create, :tags {:query-v [:showing], :cached? true, :reaction "rx51"}, :child-of 105, :start 647761.7550000001, :duration 0.05999999993946403, :end 647761.8150000001} {:id 108, :operation nil, :op-type :raf, :tags nil, :child-of nil, :start 647771.8600000001, :duration 0.09999999997671694, :end 647771.9600000001} {:id 109, :operation nil, :op-type :raf-end, :tags nil, :child-of 108, :start 647771.885, :duration 0.005000000121071935, :end 647771.8950000001} {:id 110, :operation nil, :op-type :reagent/quiescent, :tags nil, :child-of 108, :start 647771.9400000001, :duration 0.005000000004656613, :end 647771.9500000001}))
-
-(def new-matches '([{:id 91, :operation :initialise-db, :op-type :event, :tags {:event [:initialise-db], :app-db-before {:todos {3 {:id 3, :title "def", :done false}}, :showing :all}, :app-db-after {:todos {3 {:id 3, :title "def", :done false}}, :showing :all}}, :child-of nil, :start 647756.055, :duration 0.8649999999906868, :end 647756.93} {:id 110, :operation nil, :op-type :reagent/quiescent, :tags nil, :child-of 108, :start 647771.9400000001, :duration 0.005000000004656613, :end 647771.9500000001}]))
-
-(deftest subscription-match-state-test
-  (let [sub-state2 (m/subscription-match-state sub-state filtered-traces new-matches)]
-    (is (= '({:last-matched-id 0
-              :reaction-state {"rx47" {:order          [:sub/run]
-                                       :previous-value {3 {:done  false
-                                                           :id    3
-                                                           :title "def"}}
-                                       :run?           true
-                                       :subscription   [:sorted-todos]
-                                       :value          {3 {:done  false
-                                                           :id    3
-                                                           :title "def"}}}
-                               "rx48" {:subscription [:todos]
-                                       :value        ({:done  false
-                                                       :id    3
-                                                       :title "def"})}
-                               "rx51" {:order          [:sub/run]
-                                       :previous-value :all
-                                       :run?           true
-                                       :subscription   [:showing]
-                                       :value          :all}
-                               "rx52" {:subscription [:visible-todos]
-                                       :value        ({:done  false
-                                                       :id    3
-                                                       :title "def"})}
-                               "rx53" {:subscription [:all-complete?]
-                                       :value        false}
-                               "rx56" {:subscription [:footer-counts]
-                                       :value        [1
-                                                      0]}
-                               "rx57" {:subscription [:completed-count]
-                                       :value        0}}}
-              {:last-matched-id 0
-               :reaction-state {"rx47" {:order          [:sub/run]
-                                        :previous-value {3 {:done  false
-                                                            :id    3
-                                                            :title "def"}}
-                                        :run?           true
-                                        :subscription   [:sorted-todos]
-                                        :value          {3 {:done  false
-                                                            :id    3
-                                                            :title "def"}}}
-                                "rx48" {:subscription [:todos]
-                                        :value        ({:done  false
-                                                        :id    3
-                                                        :title "def"})}
-                                "rx51" {:order          [:sub/run]
-                                        :previous-value :all
-                                        :run?           true
-                                        :subscription   [:showing]
-                                        :value          :all}
-                                "rx52" {:subscription [:visible-todos]
-                                        :value        ({:done  false
-                                                        :id    3
-                                                        :title "def"})}
-                                "rx53" {:subscription [:all-complete?]
-                                        :value        false}
-                                "rx56" {:subscription [:footer-counts]
-                                        :value        [1
-                                                       0]}
-                                "rx57" {:subscription [:completed-count]
-                                        :value        0}}})
-           sub-state2))))


Rework deftag to def a TaggedVal ctor and pred

--- src/detritus/variants.clj
+++ src/detritus/variants.clj
@@ -66,12 +66,30 @@
     (-val x)))

 (defmacro deftag
-  "Defines a tagged value constructor with a namespace qualified keyword tag,
-  and a body map with keyword named members. Preconditions on members may be
+  "Generates a tagged value smart constructor `->T` where T is the name of the
+  tag. The constructor accepts an arglist identical to the list of members and
+  returns an instance of ATaggedVal with the defined tag and a map constructed
+  from keywordized member names to given values. Preconditions on members may be
   specified by the pre-map as for clojure.core/defn.

-  Ex. (deftag test \"A demo variant\" [a b]
-        {:pre [(number? a) (vector? b)]})"
+  Also generates a predicate `T?` where T is the name of the tag. The predicate
+  will return true if and only if the argument value is `tagged?`, an instance
+  of the given tag type, and satisfies the `:pre` conditions in the tag
+  constructor if any.
+
+  Ex. => (deftag test \"A demo variant\" [a b]
+      =>   {:pre [(number? a) (vector? b)]})
+      nil
+      => (->test 1 [1])
+      (:user/test {:a 1 :b [1]})
+      => (test? (->test 1 [1]))
+      true
+      => (tagged? (->test 1 [1]))
+      true
+      => (tag (->test 1 [1]))
+      :user/test
+      => (val (->test 1 [1]))
+      {:a 1 b [1]}"
   {:arglists '([name doc-string? attr-map? members pre-map?])}
   [vname & args]
   (let [;; Parse direct args
@@ -92,16 +110,17 @@
                                  :variants/tag true
                                  :tag/members  kw-members
                                  :tag/tag      kw-tag)]
-    `(do (defn ~vname ~?docstring ~?attr-map ~members
+    `(do (defn ~(symbol (str "->" (name vname))) ~?docstring ~?attr-map ~members
            ~?pre-map
-           [~kw-tag (hash-map ~@(interleave kw-members members))])
+           (->ATaggedVal ~kw-tag (hash-map ~@(interleave kw-members members))))
          (defn ~(symbol (str (name vname) "?"))
            ([x#]
-            (and (vector? x#)
-                 (= 2 (count x#))
-                 (= ~kw-tag (first x#))
-                 (or (map? (second x#))
-                     (nil? (second x#))))))
+            (and (tagged? x#)
+                 (= ~kw-tag (tag x#))
+                 (or (map? (val x#))
+                     (nil? (val x#)))
+                 (let [[_ {:keys ~members}] x#]
+                   (and ~@(:pre ?pre-map))))))
          nil)))

 (defmacro defvariant