Working on problem 0103.

Working on problem 0103.

error: pathspec 'src/project_euler/problem_0103.clj' did not match any file(s) known to git

--- src/project_euler/problem_0103.clj
+++ src/project_euler/problem_0103.clj
@@ -0,0 +1,68 @@
+(ns project-euler.problem_0103
+  (:require [clojure.math.combinatorics :as combo]))
+
+;; Let S(A) represent the sum of elements in set A of size n.
+;; We shall call it a special sum set if for any two non-empty disjoint subsets, B and C,
+;; the following properties are true:
+
+;; S(B) ≠ S(C); that is, sums of subsets cannot be equal.
+;; If B contains more elements than C then S(B) > S(C).
+;; If S(A) is minimised for a given n, we shall call it an optimum special sum set.
+;; The first five optimum special sum sets are given below.
+
+;; n = 1: {1}
+;; n = 2: {1, 2}
+;; n = 3: {2, 3, 4}
+;; n = 4: {3, 5, 6, 7}
+;; n = 5: {6, 9, 11, 12, 13}
+
+;; It seems that for a given optimum set, A = {a1, a2, ... , an},
+;; the next optimum set is of the form B = {b, a1+b, a2+b, ... ,an+b},
+;; where b is the "middle" element on the previous row.
+
+;; By applying this "rule" we would expect the optimum set for n = 6 to be A = {11, 17, 20, 22, 23, 24},
+;; with S(A) = 117.
+;; However, this is not the optimum set, as we have merely applied an algorithm to provide a near optimum set.
+;; The optimum set for n = 6 is A = {11, 18, 19, 20, 22, 25},
+;; with S(A) = 115 and corresponding set string: 111819202225.
+
+;; Given that A is an optimum special sum set for n = 7, find its set string.
+
+;; NOTE: This problem is related to Problem 105 and Problem 106.
+
+(defn next-near-optimum-set [xs]
+  (let [middle (nth xs (quot (count xs) 2))]
+    (vec (cons middle (map #(+ middle %) xs)))))
+
+(defn is-valid? [xs]
+  (let [cnt (count xs)]
+    (and (->> (combo/partitions xs)
+              (mapcat #(combo/combinations % 2))
+              (filter (fn [[ys zs]] (== (reduce + ys) (reduce + zs))))
+              (seq)
+              (not)
+              )
+         (->> (range 1 cnt)
+              (remove (fn [n] (> (reduce + (take (inc n) xs))
+                                 (reduce + (drop (- cnt n) xs)))))
+              (seq)
+              (not)
+              )
+         )))
+
+(defn search-optimum [xs]
+  (let [cnt (count xs)]
+    (->> (combo/selections [-3 -2 -1 0 1 2 3] cnt)
+         (filter (fn [ds] (< (reduce + ds) 0)))
+         (map (fn [ds] (map + xs ds)))
+         (filter #(apply distinct? %))
+         (map sort)
+         (set)
+         (filter is-valid?)
+         ;;(count)
+         )))
+
+(defn solution []
+  (->> (next-near-optimum-set [11 18 19 20 22 25])
+       (search-optimum)
+       ))


Add Leiningen configuration

Add Leiningen configuration

error: pathspec '.lein/profiles.clj' did not match any file(s) known to git

--- .lein/profiles.clj
+++ .lein/profiles.clj
@@ -0,0 +1,9 @@
+{:user {:plugins      [[refactor-nrepl "2.2.0"]
+                       [cider/cider-nrepl "0.14.0"]
+                       [com.jakemccrary/lein-test-refresh "0.18.0"]
+                       [lein-kibit "0.1.2"]
+                       [lein-environ "1.0.1"]
+                       [io.aviso/pretty "0.1.31"]
+                       [lein-ancient "0.6.10"]]
+        :dependencies [[org.clojure/tools.nrepl "0.2.12"]
+                       [io.aviso/pretty "0.1.31"]]}}


re-commence battle with ritz - javadoc working

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/sw1nn/dotfiles.git/'


Use node based repl instead of nashorn.

Use node based repl instead of nashorn.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/tcsavage/cats.git/'


Initial commit of a rule to transfer direct links to bioworld

This rule should act upon the nodes of bioworld that were generated in
step_a of this rule series. Note: this rule may also include the
ObjectProperty hierarchy output that is being queried in step_b of this
rule series.

fatal: unable to access 'https://github.com/bill-baumgartner/kabob.git/': The requested URL returned error: 403


Comments for deps

Comments for deps

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jffry/imgcast.git/'


running values

running values

fatal: remote error: upload-pack: not our ref 08e25c433a0b4a57f369b659bec70275576a0fb0
fatal: the remote end hung up unexpectedly


Minor cleanup.

Minor cleanup.

--- spec/freefrog/rest_spec.clj
+++ spec/freefrog/rest_spec.clj
@@ -23,9 +23,9 @@
             [clj-http.client :as http-client]
             [freefrog.rest :as r]
             [freefrog.persistence :as p])
-  (:use [ring.adapter.jetty])
   (:import [javax.persistence EntityNotFoundException]
-           [org.apache.http HttpStatus]))
+           [org.apache.http HttpStatus])
+  (:use [ring.adapter.jetty]))

 (def test-server (ref nil))

@@ -60,10 +60,10 @@

 (def sample-gov-log {:body "Add role\nRename accountability."})

-(defn circle-not-found-thrower [& args]
+(defn throw-circle-not-found [& args]
   (throw (EntityNotFoundException. "Circle does not exist")))

-(defn govt-meeting-not-found-thrower [& args]
+(defn throw-meeting-not-found [& args]
   (throw (EntityNotFoundException. "Governance meeting does not exist")))

 (defmacro it-responds-with-status [expected-status response]
@@ -84,10 +84,10 @@

   (context "with a non-existent circle"
     (around [it]
-      (with-redefs [p/get-all-governance-logs circle-not-found-thrower
-                    p/new-governance-log circle-not-found-thrower
-                    p/get-governance-log circle-not-found-thrower
-                    p/put-governance-log circle-not-found-thrower]
+      (with-redefs [p/get-all-governance-logs throw-circle-not-found
+                    p/new-governance-log throw-circle-not-found
+                    p/get-governance-log throw-circle-not-found
+                    p/put-governance-log throw-circle-not-found]
         (it)))

     (context "requesting the governance endpoint"
@@ -139,7 +139,7 @@

     (context "with a non-existent governance endpoint"
       (around [it]
-        (with-redefs [p/get-governance-log govt-meeting-not-found-thrower]
+        (with-redefs [p/get-governance-log throw-meeting-not-found]
           (it)))

       (context "putting to the agenda endpoint"


added file also

added file also

error: pathspec 'src/epicea/utils/file.clj' did not match any file(s) known to git

--- src/epicea/utils/file.clj
+++ src/epicea/utils/file.clj
@@ -0,0 +1,4 @@
+(ns epicea.utils.file)
+
+(defn exists? [x]
+  (.exists (java.io.File. x)))


I miss clojure a bit

I miss clojure a bit

error: pathspec 'Add-Two-Numbers/ATN.clj' did not match any file(s) known to git

--- Add-Two-Numbers/ATN.clj
+++ Add-Two-Numbers/ATN.clj
@@ -0,0 +1,15 @@
+(defn add-two-number [x y]
+  (loop [a x
+         b y
+         re []]
+    (print x y re)
+    (cond (and (empty? a) (empty? b))
+          re
+          (empty? a)
+          (into [] (concat re b))
+          (empty? b)
+          (into [] (concat re b))
+          :else
+          (recur (into [] (rest a))
+                 (into [] (rest b))
+                 (conj re (+ (first a) (first b)))))))


:8ball: clojure bob - it compiles

:8ball: clojure bob - it compiles

fatal: unable to access 'https://github.com/ullet/exercism.git/': The requested URL returned error: 403


Add basic make-cpu func

Add basic make-cpu func

Signed-off-by: Yen-Chin Lee <082d453d72dce940e12089a4ad48b97cfe1f3ec4@gmail.com>

error: pathspec 'src/emulator_chip8/cpu.cljc' did not match any file(s) known to git

--- src/emulator_chip8/cpu.cljc
+++ src/emulator_chip8/cpu.cljc
@@ -0,0 +1,54 @@
+(ns emulator-chip8.cpu)
+
+(defrecord State [])
+
+(defn make-cpu
+  ([& {:keys [memory stack SP PC V I DT ST]
+       :or {SP 0
+            PC 0x200
+            I  0
+            DT 0
+            ST 0}}]
+   (State.
+    nil {;; CHIP-8 only has 4096 bytes (4KB) memory (0x0 ~ 0xFFF).
+         ;;
+         ;; The first 512 bytes, from 0x000 to 0x1FF, are where the
+         ;; original interpreter was located, and should not used by programs.
+         :memory (vec (take 4096 (concat memory (repeat 4096 0))))
+
+         ;; The stack is used to remember the current location
+         ;; before a jump is performed. The system has 16 levels
+         ;; of stack and in order to remember which level of the
+         ;; stack is used.
+         :stack (vec (take 16 (concat stack (repeat 16 0))))
+
+         ;; The stack pointer (SP) can be 8-bit, it is used to point
+         ;; to the topmost level of the stack.
+         :SP SP
+
+         ;; Most CHIP-8 programs start at locastion 0x200 (512),
+         ;; but some begin at 0x600 (1536).
+         ;; The program counter (PC) should be 16-bit, and is used
+         ;; to store the currently executing address.
+         :PC PC
+
+         ;; V-registers, CHIP-8 has 15 8-bit general purpose registers
+         ;; named V0, V1 ~ VE. The 16th register is used for
+         ;; the `carry flag`.
+         :V (vec (take 16  (concat V (repeat 16 0))))
+
+         ;; I-register is used to store memory address
+         :I I
+
+         ;; The delay timer is active whenever the delay timer
+         ;; register (DT) is non-zero.
+         ;; This timer does nothing more than subtract 1 from the
+         ;; value of DT at a rate of 60Hz. When DT reaches 0, it deactivates.
+         :DT DT
+
+         ;; The sound timer is active whenever the sound timer
+         ;; register (ST) is non-zero. This timer also decrements
+         ;; at a rate of 60Hz, however, as long as ST's value is
+         ;; greater than zero, the Chip-8 buzzer will sound. When ST
+         ;; reaches zero, the sound timer deactivates.
+         :ST ST})))


Remove spurious save-data

Remove spurious save-data

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mtravers/incidents.git/'


[WM] set content-type on S3 uploads

[WM] set content-type on S3 uploads

Otherwise we loose non-ASCII characters (they become '?'). Set to
"text/plain; charset=UTF-8".

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/scheduled-message-works.git/'


Fix typo

Fix typo

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/physion/ovation-webapi.git/'


Problem 0097.

Problem 0097.

error: pathspec 'src/project_euler/problem_0097.clj' did not match any file(s) known to git

--- src/project_euler/problem_0097.clj
+++ src/project_euler/problem_0097.clj
@@ -0,0 +1,28 @@
+(ns project-euler.problem-0097)
+
+;; The first known prime found to exceed one million digits was discovered in 1999,
+;; and is a Mersenne prime of the form 2^6972593−1; it contains exactly 2,098,960 digits.
+;; Subsequently other Mersenne primes, of the form 2^p−1, have been found which contain more digits.
+
+;; However, in 2004 there was found a massive non-Mersenne prime which contains 2,357,207 digits:
+;; 28433×2^7830457+1.
+
+;; Find the last ten digits of this prime number.
+
+(defn mult-mod [m x y]
+  (rem (*' x y) m)
+  )
+
+(defn pow-mod [m x n]
+  (loop [p 1, n n, e x]
+    (if (zero? n)
+      p
+      (let [p' (if (odd? n) (mult-mod m p e) p)]
+        (recur p' (quot n 2) (mult-mod m e e))
+        ))))
+
+(defn solution []
+  (let [m 10000000000]
+    (+ 1 (mult-mod m 28433 (pow-mod m 2 7830457)))))
+
+;;-> 8739992577


First whack at undertow websockets (complete but untested)

error: pathspec 'web/src/immutant/web/websocket.clj' did not match any file(s) known to git

--- web/src/immutant/web/websocket.clj
+++ web/src/immutant/web/websocket.clj
@@ -0,0 +1,91 @@
+;; Copyright 2014 Red Hat, Inc, and individual contributors.
+;;
+;; Licensed under the Apache License, Version 2.0 (the "License");
+;; you may not use this file except in compliance with the License.
+;; You may obtain a copy of the License at
+;;
+;; http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+
+(ns immutant.web.websocket
+  (:require [clojure.string :as str]
+            [clojure.java.io :as io]
+            [immutant.web.undertow :refer [create-http-handler]])
+  (:import [java.nio ByteBuffer]
+           [org.xnio ChannelListener]
+           [io.undertow.websockets WebSocketProtocolHandshakeHandler WebSocketConnectionCallback]
+           [io.undertow.websockets.spi WebSocketHttpExchange]
+           [io.undertow.websockets.core WebSocketChannel WebSockets AbstractReceiveListener
+            BufferedTextMessage BufferedBinaryMessage CloseMessage]
+           [io.undertow.server.handlers ResponseCodeHandler]))
+
+(defn send!
+  [channel message & [callback]]
+  (letfn [(bytes? [x] (= Byte/TYPE (.getComponentType (class x))))]
+    (cond
+      (string? message)
+      (WebSockets/sendText message channel callback)
+      (bytes? message)
+      (WebSockets/sendBinary (ByteBuffer/wrap message) channel callback)
+      :else (throw (IllegalArgumentException. "Message must be a String or byte[]")))))
+
+(defn- callback
+  [f & args]
+  (when f (apply f args)))
+
+(defn- callback-close
+  "TODO: remove this once onCloseMessage is available"
+  [on-close ^WebSocketChannel channel, ^BufferedBinaryMessage message]
+  (when on-close
+    (let [data (.getData message)]
+      (try
+        (let [cm (CloseMessage. (.getResource data))]
+          (on-close channel {:code (.getReason cm) :reason (.getString cm)}))
+        (finally
+          (.free data))))))
+
+(defn- callback-binary-message
+  "TODO: figure out messages across multiple ByteBuffers"
+  [on-message ^WebSocketChannel channel, ^BufferedBinaryMessage message]
+  (when on-message
+    (let [data (.getData message)]
+      (try
+        (let [payload (.getResource data)
+              buffer (first payload)]
+          (if (and buffer (.hasArray buffer) (= 1 (count payload)))
+            (on-message (.array buffer))
+            (throw (UnsupportedOperationException. "TODO: binary messages across multiple ByteBuffers"))))
+        (finally
+          (.free data))))))
+
+(defn create-handler
+  "The following callbacks are supported:
+    :on-message (fn [message])
+    :on-open    (fn [channel])
+    :on-close   (fn [channel {:keys [:code :reason]}])
+    :on-error   (fn [channel Throwable])
+    :fallback   (fn [request] response), i.e. a valid Ring handler"
+  [& {:keys [on-message on-open on-close on-error fallback]}]
+  (WebSocketProtocolHandshakeHandler.
+    (reify WebSocketConnectionCallback
+      (^void onConnect [_ ^WebSocketHttpExchange exchange ^WebSocketChannel channel]
+        (callback on-open channel)
+        (.. channel getReceiveSetter
+          (set (proxy [AbstractReceiveListener] []
+                 (onError [^WebSocketChannel channel, ^Throwable error]
+                   (proxy-super onError channel error)
+                   (callback on-error channel error))
+                 (onFullCloseMessage [^WebSocketChannel channel, ^BufferedBinaryMessage message]
+                   ;; TODO: Use onCloseMessage to avoid having to call super
+                   (proxy-super onFullCloseMessage channel message)
+                   (callback-close on-close channel message))
+                 (onFullTextMessage [^WebSocketChannel channel, ^BufferedTextMessage message]
+                   (callback on-message (.getData message)))
+                 (onFullBinaryMessage [^WebSocketChannel channel, ^BufferedBinaryMessage message]
+                   (callback-binary-message on-message channel message)))))))
+    (if fallback (create-http-handler fallback) ResponseCodeHandler/HANDLE_404)))


drop unuse code

drop unuse code

Signed-off-by: Yen-Chin Lee <082d453d72dce940e12089a4ad48b97cfe1f3ec4@gmail.com>

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/coldnew/pomodo.git/'


[TH] barf out params for query

[TH] barf out params for query

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/electorate-works.git/'


Improved debug output (fisheye)

Improved debug output (fisheye)

--- boot/core/src/boot/task/built_in.clj
+++ boot/core/src/boot/task/built_in.clj
@@ -152,8 +152,8 @@
                     changed (watcher)]
                 (when-not (empty? changed)
                   (when verbose
-                    (doseq [[op p f] changed]
-                      (util/info (format "→ %s %s %s\n" op (.lastModified f) p)))
+                    (doseq [[op p _] changed]
+                      (util/info (format "\u25C9 %s %s\n" op p)))
                     (util/info "\n"))
                   (binding [*out* (if quiet (new java.io.StringWriter) *out*)
                             *err* (if quiet (new java.io.StringWriter) *err*)]


Namespace partner-site interceptor name

Namespace partner-site interceptor name

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/turbovote-http-api.git/'


Added compojure.handler namespace

Added compojure.handler namespace

error: pathspec 'src/compojure/handler.clj' did not match any file(s) known to git

--- src/compojure/handler.clj
+++ src/compojure/handler.clj
@@ -0,0 +1,22 @@
+(ns compojure.handler
+  (:use [ring.middleware params
+                         keyword-params
+                         nested-params
+                         multipart-params
+                         cookies
+                         session]))
+
+(defn api
+  "Create a handler suitable for a web API."
+  [routes]
+  (-> routes
+      wrap-keyword-params
+      wrap-nested-params
+      wrap-params))
+
+(defn site
+  "Create a handler suitable for a standard website."
+  [routes]
+  (-> (api routes)
+      wrap-multipart-params
+      wrap-session))


finish clojure version; it has been a long time...

error: pathspec 'Combination-Sum-II/CS2.clj' did not match any file(s) known to git

--- Combination-Sum-II/CS2.clj
+++ Combination-Sum-II/CS2.clj
@@ -0,0 +1,17 @@
+(defn combination-sum2 [cands target]
+  (let [cands (sort cands)
+        list-of-sets (doall (for [_ (range (inc target))]
+                              (atom #{})))]
+
+    (swap! (nth list-of-sets 0) (fn [x] (conj x [])))
+
+    (doseq [cand cands
+            t (range target (dec cand) -1)
+            prev @(nth list-of-sets (- t cand))]
+
+      (swap! (nth list-of-sets t)
+             conj
+             (conj prev cand)))
+
+    @(last list-of-sets)
+    ))


Add scrape_wa_trs.clj.

Add scrape_wa_trs.clj.

error: pathspec 'project/get-data/src/get_data/scrape_wa_trs.clj' did not match any file(s) known to git

--- project/get-data/src/get_data/scrape_wa_trs.clj
+++ project/get-data/src/get_data/scrape_wa_trs.clj
@@ -0,0 +1,26 @@
+(ns scrape-wa-trs
+  (:require [scrape-trs.core :refer [get-trip-reports]]))
+
+(comment
+  "TODO:
+   - upgrade scrape-trs to have error handling strategy
+     page could not load
+     expected content could not be there
+   - retrieve cc.com tr list pages for each region in WA (POST)
+   - retrieve sp.com tr list page for WA
+   - get-trip-reports on each page and concat all together
+   - save to csv"
+
+  (def cascade-climbers-washington-regions
+    #{"Alpine Lakes"
+      "Central/Eastern  Washington"
+      "Columbia River Gorge"
+      "Ice Climbing Forum"
+      "Mount Rainier NP"
+      "North Cascades"
+      "Olympic Peninsula"
+      "Rock Climbing Forum"
+      "Southern WA Cascades"
+      "the *freshiezone*"}))
+
+(defn -main [& args])


/account POSTs spec complete

/account POSTs spec complete

fatal: unable to access 'https://github.com/CraZySacX/glitter.git/': The requested URL returned error: 403


Linear regression

Linear regression

error: pathspec 'src/mekena/linear-reg.clj' did not match any file(s) known to git

--- src/mekena/linear-reg.clj
+++ src/mekena/linear-reg.clj
@@ -0,0 +1,92 @@
+(ns mekena.linear-reg
+  (:require [incanter.core :as icore]
+            [incanter.io :as io]
+            [incanter.stats :as stats]
+            [incanter.charts :as charts]))
+
+;; Stanford Machine Learning using Clojure and Incanter
+;; machine learning hw1: linear regression
+(icore/view (charts/scatter-plot
+              :col0
+              :col1
+              :data (io/read-dataset "./resources/ex1data1.txt")
+              :x-label "Population of City in 10,000s"
+              :y-label "Profit in $10,000s"))
+
+;; config params
+(def alpha 0.01)
+(def iterations 1500)
+
+(defn h-ftn
+  "The hypothesis function : h-theta(x) = theta0 + (theta1 * x)
+  we add a column of 1 to x to produce a mx2 matrix.
+  x and theta are matrices: x is mx2, theta is 2x1"
+  [t0 t1 x]
+  (->> x
+       (map (partial * t1))
+       (map (partial + t0))))
+
+;; TODO eliminate repetitions
+(defn calc-theta0
+  [x y theta]
+  (let [t0 (first theta)
+        t1 (second theta)]
+    (as-> x _
+      (h-ftn t0 t1 _)
+      (map - _ y)
+      (reduce + _)
+      (/ _ (count x))
+      (* alpha _))))
+
+(defn calc-theta1
+  [x y theta]
+  (let [t0 (first theta)
+        t1 (second theta)]
+    (as-> x _
+      (h-ftn t0 t1 _)
+      (map - _ y)
+      (map * _ x)
+      (reduce + _)
+      (/ _ (count x))
+      (* alpha _))))
+
+(defn calc-theta
+  [x y theta]
+  (map - theta ((juxt (partial calc-theta0 x y) (partial calc-theta1 x y)) theta)))
+
+(defn gradient-descent-history
+  "Get theta values for last 10 iterations, for debugging really"
+  [x y]
+  (drop (- iterations 10) (take iterations (iterate (partial calc-theta x y) [0 1]))))
+
+(defn gradient-descent
+  "Calculate gradient descent"
+  [x y]
+  (drop (dec iterations) (take iterations (iterate (partial calc-theta x y) [0 1]))))
+
+(defn predict-value
+  [x xs ys]
+  (as-> xs _
+    (gradient-descent _ ys)
+    (flatten _)
+    (+ (first _) (* x (second _)))))
+
+(defn compute-mse
+  "Calculate the cost (mse : mean square error) function: 1/2m * Sigma(from 1,m) (Theta^T*X - Y)^2"
+  [x y theta]
+  (let [t0 (first theta)
+        t1 (second theta)]
+    (as-> x _
+      (h-ftn t0 t1 _)
+      (map - _ y)
+      (map (fn [n] (* n n)) _)
+      (reduce + _)
+      (/ _ (* 2 (count x))))))
+
+(defn calc-mse-hist
+  "Verify that mean error square to decreasing"
+  [x y]
+  (->> y
+       (gradient-descent-history x)
+       (map (partial compute-mse x y))))
+


New core namespace

New core namespace

error: pathspec 'src/muon_clojure/core.clj' did not match any file(s) known to git

--- src/muon_clojure/core.clj
+++ src/muon_clojure/core.clj
@@ -0,0 +1,214 @@
+(ns muon-clojure.core
+  (:require [muon-clojure.utils :as mcu]
+            [muon-clojure.common :as mcc]
+            [clojure.tools.logging :as log]
+            [clojure.core.async :refer [go-loop go <! >! chan buffer close!]]
+            [muon-clojure.rx :as rx]
+            [com.stuartsierra.component :as component])
+  (:use clojure.java.data)
+  (:import (io.muoncore.protocol.requestresponse Response)
+           (io.muoncore.exception MuonException)
+           (org.reactivestreams Publisher)
+           (io.muoncore.protocol.event.client DefaultEventClient)
+           (io.muoncore.protocol.event ClientEvent)
+           (io.muoncore Muon MuonStreamGenerator)
+           (io.muoncore.api MuonFuture ImmediateReturnFuture)
+           (io.muoncore.channel ChannelConnection
+                                ChannelConnection$ChannelFunction)
+           (io.muoncore.protocol.event.server EventServerProtocolStack)
+           (com.google.common.eventbus EventBus)
+           (java.util.function Predicate)
+           (java.util Map)))
+
+(def ^:dynamic *muon-config* nil)
+
+(defprotocol MicroserviceStream (stream-mappings [this]))
+(defprotocol MicroserviceRequest (request-mappings [this]))
+(defprotocol MicroserviceEvent (handle-event [this event]))
+(defprotocol ClientConnection
+  (wiretap [this])
+  (request [this service-url params])
+  (subscribe [this service-url params]))
+
+(defn expose-streams! [muon mappings]
+  (dorun (map #(mcc/stream-source
+                muon (:endpoint %) (:stream-type %) (:fn-process %))
+              mappings)))
+
+(defn expose-requests! [muon mappings]
+  (dorun (map #(mcc/on-request muon (:endpoint %) (:fn-process %))
+              mappings)))
+
+(defn impl-request [muon service-url params]
+  (log/trace (pr-str params))
+  (let [response (.request muon service-url params Map)]
+    (log/trace "Response:" (pr-str response))
+    (let [got-response (.get response)
+          payload (.getPayload got-response)]
+      (log/trace "Response payload:" (pr-str payload))
+      payload)))
+
+(defn params->uri [service-url params]
+  (let [query-string (map #(str (name (key %)) "=" (val %)) params)
+        url-string (str service-url "?"
+                        (clojure.string/join "&" query-string))
+        uri (java.net.URI. url-string)]
+    (log/trace "Query string:" url-string)
+    uri))
+
+(defn impl-subscribe [muon service-url params]
+  (let [uri (params->uri service-url params)
+        ch (chan 1024)] ;; TODO: Increase this number?
+    (go
+      (let [failsafe-ch (chan)]
+        (.subscribe muon uri Map (rx/subscriber failsafe-ch))
+        (log/trace "Starting processing loop for" (.hashCode failsafe-ch))
+        (loop [ev (<! failsafe-ch) timeout 1]
+          (log/trace "Arrived" ev "for" (.hashCode failsafe-ch))
+          (if (nil? ev)
+            (do
+              (log/info ":::::: Stream closed")
+              (close! failsafe-ch)
+              (close! ch))
+            (let [thrown? (instance? Throwable ev)]
+              (>! ch (mcu/keywordize ev))
+              (log/trace "Client received" (pr-str ev))
+              (if thrown?
+                (if (and (instance? MuonException ev)
+                         (= (.getMessage ev) "Stream does not exist"))
+                  (do
+                    (log/info "Stream does not exist, shutting down")
+                    (close! failsafe-ch)
+                    (close! ch))
+                  (do
+                    (log/info (str "::::::::::::: Stream failed, resubscribing after "
+                                   timeout "ms..."))
+                    (Thread/sleep timeout)
+                    (.subscribe muon uri Map (rx/subscriber failsafe-ch))
+                    (recur (<! failsafe-ch) (* 2 timeout))))
+                (recur (<! failsafe-ch) 1)))))
+        (log/trace "Subscription ended")))
+    ch))
+
+(defn channel-function [implementation]
+  (reify ChannelConnection$ChannelFunction
+    (apply [_ event-wrapper]
+      (let [event-raw (.getEvent event-wrapper)
+            event {:event-type (.getEventType event-raw)
+                   :stream-name (.getStreamName event-raw)
+                   :schema (.getSchema event-raw)
+                   :caused-by (.getCausedById event-raw)
+                   :caused-by-relation (.getCausedByRelation event-raw)
+                   :service-id (.getService event-raw)
+                   :order-id (.getOrderId event-raw)
+                   :event-time (.getEventTime event-raw)
+                   :payload (mcu/keywordize
+                             (into {} (.getPayload event-raw)))}
+            {:keys [order-id event-time]} (handle-event implementation event)]
+        (.persisted event-wrapper order-id event-time)))))
+
+(declare muon-client)
+
+(defrecord Microservice [options]
+  ClientConnection
+  (wiretap [this] (:wiretap this))
+  (request [this service-url params]
+    (impl-request (:muon this) service-url params))
+  (subscribe [this service-url params]
+    (impl-subscribe (:muon this) service-url params))
+  component/Lifecycle
+  (start [component]
+    (if (nil? (:muon component))
+      (let [implementation (:implementation options)
+            options (if (and (not (nil? implementation))
+                             (satisfies? MicroserviceEvent implementation))
+                      (update options :tags conj "eventstore")
+                      options)
+            muon (apply muon-client
+                        (:url options) (:service-name options) (:tags options))
+            tc (.getTransportControl (:muon muon))
+            debug? (true? (:debug options))
+            taps (if debug?
+                   (let [tap (.tap tc
+                                   (reify Predicate (test [_ _] true)))
+                         ch (chan 1024)]
+                     (.subscribe tap (rx/subscriber ch))
+                     {:wiretap ch :tap tap})
+                   {})]
+        (set! (. io.muoncore.channel.async.StandardAsyncChannel echoOut)
+              debug?)
+        (when-not (nil? implementation)
+          (if (satisfies? MicroserviceStream implementation)
+            (expose-streams! (:muon muon) (stream-mappings implementation)))
+          (if (satisfies? MicroserviceRequest implementation)
+            (expose-requests! (:muon muon) (request-mappings implementation)))
+          (if (satisfies? MicroserviceEvent implementation)
+            (let [handler (channel-function implementation)
+                  event-stack (EventServerProtocolStack.
+                               handler (.getCodecs (:muon muon)))]
+              (.registerServerProtocol
+               (.getProtocolStacks (:muon muon)) event-stack))))
+        (merge component (merge taps muon)))
+      component))
+  (stop [{:keys [muon] :as component}]
+    (if (nil? (:muon component))
+      component
+      (do
+        (try
+          (if-let [wiretap (:wiretap component)]
+            (close! wiretap))
+          #_(if-let [tap (:tap component)]
+            (.shutdown tap))
+          ;; TODO: Re-check if transport and discovery
+          ;;       have to be shut down
+          (.shutdown muon))
+        (merge component {:muon nil :event-client nil
+                          :wiretap nil :tap nil})))))
+
+(defn micro-service [options]
+  (map->Microservice {:options (assoc options :debug false)}))
+
+(defn muon-client [url service-name & tags]
+  (let [muon-instance (mcc/muon-instance url service-name tags)
+        ec (try
+             ;; TODO: Make event client handling smarter
+             (DefaultEventClient. muon-instance)
+             (catch MuonException e
+               (log/info (str "Eventstore not found, "
+                              "event functionality not available!"))
+               nil))
+        client (map->Microservice
+                {:muon muon-instance :event-client ec})]
+    #_(Thread/sleep 2000)
+    client))
+
+(defmacro with-muon [muon & body]
+  `(binding [*muon-config* ~muon]
+     ~@body))
+
+(defn event! [{:keys [event-type stream-name schema caused-by
+                      caused-by-relation #_service-id payload]
+               :as event}]
+  ;; TODO: Make event client handling smarter
+  (if-let [ec (:event-client *muon-config*)]
+    (let [ev (ClientEvent. event-type stream-name schema caused-by
+                           caused-by-relation #_service-id
+                           (mcu/dekeywordize payload))
+          res (.event ec ev)]
+      (merge event {:order-id (.getOrderId res)
+                    :event-time (.getEventTime res)}))
+    (throw (UnsupportedOperationException. "Eventstore not available"))))
+
+(defn subscribe!
+  [service-url & {:keys [from stream-type stream-name]
+                  :or {from (System/currentTimeMillis) stream-type nil
+                       stream-name "events"}}]
+  (let [params (mcu/dekeywordize {:from (str from) :stream-type stream-type
+                                  :stream-name stream-name})]
+    (log/info ":::::::: CLIENT SUBSCRIBING" service-url params)
+    (subscribe *muon-config* service-url params)))
+
+(defn request! [service-url params]
+  (let [item-json (mcu/dekeywordize params)]
+    (log/info ":::::::: CLIENT REQUESTING" service-url item-json)
+    (mcu/keywordize (into {} (request *muon-config* service-url item-json)))))


Sketch of a convman

Sketch of a convman

error: pathspec 'src/polismath/convman.clj' did not match any file(s) known to git

--- src/polismath/convman.clj
+++ src/polismath/convman.clj
@@ -0,0 +1,58 @@
+(ns polismath.convman
+  (:require [clojure.core.async :as async :refer [>!! <!! >! <! chan go]]))
+
+
+(defn drain!
+  "Given core.async chan c, return lazy-seq of queued messages which terminates as
+  soon as the channel is empty"
+  [c]
+  (let [cc (chan 1)]
+    (go (>! cc ::queue-empty))
+    (letfn
+      ; This fn does all the hard work, but closes over cc to avoid reconstruction
+      [(drainer! [c]
+         (let [[v _] (<!! (go (async/alts! [c cc] :priority true)))]
+           (if (= v ::queue-empty)
+             (lazy-seq [])
+             (lazy-seq (cons v (drainer! c))))))]
+      (drainer! c))))
+
+
+(defprotocol IManager
+  (enqueue [this message])
+  (ping [this]))
+
+
+(defrecord Manager [queue conv]
+  IManager
+  (enqueue [_ message]
+    (go (>! queue message)))
+  (ping [_]
+    (send conv identity)))
+
+
+(defn queued-agent [& {:keys [buffer update-fn] :or {:buffer 1000000}}]
+  (let [c (chan buffer)
+        a (agent {:sid [] :val []})]
+    ; Set up the queue
+    (add-watch
+      conv
+      :update-conv
+      (fn [k r o n]
+        (let [queued (drain! c)]
+          (when-not (empty? queued)
+            (send a update-fn queued)))))
+    (Manager. c a)))
+
+
+(defn -main []
+  (println "starting")
+  (let [c (chan 100)]
+    ; First, add some data to our channel
+    (doseq [x (range 10)]
+      (>!! c x))
+    (println "here we go" (into [] (drain! c)))
+    ; end of let; ready to shutdown
+    (println "done")))
+
+


First cut at VictorOps integration

First cut at VictorOps integration

error: pathspec 'src/riemann/victorops.clj' did not match any file(s) known to git

--- src/riemann/victorops.clj
+++ src/riemann/victorops.clj
@@ -0,0 +1,54 @@
+(ns riemann.victorops
+  "Forwards events to VictorOps"
+  (:require [clj-http.client :as client])
+  (:require [cheshire.core :as json])
+  (:require [clojure.string :as cstr]))
+
+(def ^:private event-url
+  "https://alert.victorops.com/integrations/generic/20131114/alert")
+
+(defn- post
+  "POST to the VictorOps API"
+  [api-key routing-key request]
+  (client/post (cstr/join "/" [event-url api-key routing-key])
+               {:body (json/generate-string request)
+                :socket-timeout 5000
+                :conn-timeout 5000
+                :content-type :json
+                :accept :json
+                :throw-entire-message? true}))
+
+(defn- format-event
+  "Formats an event for VO. message-type is one of :INFO, :WARNING,
+  :ACKNOWLEDGEMENT, :CRITICAL, :RECOVERY"
+  [message-type event]
+  {:message_type message-type
+   :entity_id (cstr/join "/" [(:host event) (:service event)])
+   :timestamp (:time event)
+   :state_start_time (:time event)
+   :state_message (str (:host event) " "
+                     (:service event) " is "
+                     (:state event) " ("
+                     (:metric event) ")")
+   :entity_is_host false
+   :monitoring_tool "riemann"})
+
+(defn victorops
+  "Creates a VictorOps adapter. Takes your API key and routing key and returns a map of
+  functions :info, :warning, :critical, :acknowledgement and :recovery corresponding to
+  the related VictorOps API message types. Each message's entity id will be
+  \"<event host>/<event service>\". The state message will be the host, service, state
+  and metric.
+
+  (let [vo (victorops \"my-api-key\" \"my-routing-key\")]
+    (changed-state
+      (where (state \"info\") (:info vo))
+      (where (state \"warning\") (:warning vo))
+      (where (state \"critical\") (:critical vo))
+      (where (state \"ok\") (:recovery vo))))"
+  [api-key routing-key]
+  {:info            (fn [e] (post api-key routing-key (format-event :INFO e)))
+   :warning         (fn [e] (post api-key routing-key (format-event :WARNING e)))
+   :critical        (fn [e] (post api-key routing-key (format-event :CRITICAL e)))
+   :acknowledgement (fn [e] (post api-key routing-key (format-event :ACKNOWLEDGEMENT e)))
+   :recovery        (fn [e] (post api-key routing-key (format-event :RECOVERY e)))})


Preparation for Amazon - selection sort

Preparation for Amazon - selection sort

fatal: unable to access 'https://github.com/rssole/clojureplayground.git/': The requested URL returned error: 403


add services and catalogs separately into db

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/starcity-properties/odin.git/'


Gogokoak db-kon pasata

Gogokoak db-kon pasata

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lnmnd/magnet.zer.git/'


remove errant js/console.log

remove errant js/console.log


picture links now target new frame

picture links now target new frame

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/talexand/kittens-gallery.git/'


Initial support for behaviors: on-add-aspect!

error: pathspec 'src/main/clojure/alfresco/behave.clj' did not match any file(s) known to git

--- src/main/clojure/alfresco/behave.clj
+++ src/main/clojure/alfresco/behave.clj
@@ -0,0 +1,24 @@
+(ns alfresco.behave
+  (:require [alfresco.core :as c]
+            [alfresco.model :as m])
+  (:import [org.alfresco.repo.policy JavaBehaviour Behaviour$NotificationFrequency]
+           [org.alfresco.repo.node
+            NodeServicePolicies$OnAddAspectPolicy]))
+
+;; no static String to use here, unfortunately
+(defonce *policy-component* (c/get-bean "policyComponent"))
+
+(defmacro on-add-aspect!
+  "Registers a clojure behavior that will be called when an aspect with
+QName qname. The provided form f must accept two input parameters: a noderef and a qname"
+  [qname f]
+  `(let [p# (reify NodeServicePolicies$OnAddAspectPolicy
+                   (~'onAddAspect [~'this ~'node-in ~'qname-in]
+                                  (~f (c/j2c ~'node-in) (m/qname-str ~'qname-in))))
+         b# (JavaBehaviour. p#
+                            "onAddAspect"
+                            Behaviour$NotificationFrequency/TRANSACTION_COMMIT)]
+     (.bindClassBehaviour *policy-component*
+                         NodeServicePolicies$OnAddAspectPolicy/QNAME
+                         (m/qname ~qname)
+                         b#)))


note on the function of the NUL char in sequence encoding

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/QuiltProject/sedan.git/'


Don't allow old file to linger after renaming

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bsmr-clojure/Nightcode.git/'


Fix W3 HTML checker error for X-UA-Compatible

fatal: unable to access 'https://github.com/magoyette/marcandregoyette.com.git/': The requested URL returned error: 403


fix for the new privat JSON format

fix for the new privat JSON format

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mprokopov/privat24-manager.git/'


Make git read-only for now

Make git read-only for now


Fix bloom filter deserialization

Fix bloom filter deserialization

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/leif47/immutabledb-experimental.git/'


rename trace -> dtrace

rename trace -> dtrace

fatal: unable to access 'https://github.com/JulesGosnell/dada.git/': The requested URL returned error: 403


Start using :fn parameter to om/build to build indexes.

fatal: unable to access 'https://github.com/cstorey/nrod.git/': The requested URL returned error: 403


fix failing test (number -> positive-number)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jtbeckha/alda.git/'


[EN] Add comment for weird data transformation.

fatal: unable to access 'https://github.com/democracyworks/election-notification-works.git/': The requested URL returned error: 403


Implement try-clojure client.

Implement try-clojure client.

error: pathspec 'src-cljs/tranjlator/try_clojure.clj' did not match any file(s) known to git

--- src-cljs/tranjlator/try_clojure.clj
+++ src-cljs/tranjlator/try_clojure.clj
@@ -0,0 +1,32 @@
+(ns tranjlator.try-clojure
+  (:require [org.httpkit.client :as http]
+            [cheshire.core :as json]
+            [clojure.core.async :as a :refer [<! go go-loop chan >!]]))
+
+(def ^:const +http-route+ "http://tryclj.com/eval.json")
+
+(defn read-response
+  [resp]
+  (println "resp:" resp)
+  {:result (-> resp :body (json/parse-string true))
+   :cookie (get-in resp [:headers :set-cookie]
+                   (get-in resp [:opts :headers "Cookie"]))})
+
+(defn query
+  ([expr]
+     (query expr nil))
+  ([expr cookie]
+     (let [resp-chan (chan 1 (map read-response))]
+       (http/get +http-route+
+                 (merge {:query-params {:expr expr}}
+                        (when cookie
+                          {:headers {"Cookie" cookie}}))
+                 #(a/put! resp-chan %))
+       resp-chan)))
+
+(comment
+  (def result (a/<!! (query "(def foo (+ 1 1))")))
+
+  (a/<!! (query "foo" (:cookie result)))
+
+  )


gather election ids in a set to avoid db round trips

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/scheduled-message-works.git/'


convenience function for converting a time-of-day value like "morning" into an actual hour of the day value.

--- src/metabase/models/emailreport.clj
+++ src/metabase/models/emailreport.clj
@@ -50,6 +50,12 @@
    {:id "evening" :name "Evening" :realhour 20},
    {:id "midnight" :name "Midnight" :realhour 0}])

+(defn time-of-day->realhour
+  "Time-of-day to realhour"
+  [time-of-day]
+  (-> (filter (fn [tod] (= time-of-day (:id tod))) times-of-day)
+      (first)
+      (:realhour)))

 ;; ## Entity


[#237] Add original clojure.xml

[#237] Add original clojure.xml

error: pathspec 'src/clj/clojure/xml.clj' did not match any file(s) known to git

--- src/clj/clojure/xml.clj
+++ src/clj/clojure/xml.clj
@@ -0,0 +1,118 @@
+;   Copyright (c) Rich Hickey. All rights reserved.
+;   The use and distribution terms for this software are covered by the
+;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;   which can be found in the file epl-v10.html at the root of this distribution.
+;   By using this software in any fashion, you are agreeing to be bound by
+;   the terms of this license.
+;   You must not remove this notice, or any other, from this software.
+
+(ns ^{:doc "XML reading/writing."
+       :author "Rich Hickey"}
+  clojure.xml
+  (:import (org.xml.sax ContentHandler Attributes SAXException)
+           (javax.xml.parsers SAXParser SAXParserFactory)))
+
+(def ^:dynamic *stack*)
+(def ^:dynamic *current*)
+(def ^:dynamic *state*) ; :element :chars :between
+(def ^:dynamic *sb*)
+
+(defstruct element :tag :attrs :content)
+
+(def tag (accessor element :tag))
+(def attrs (accessor element :attrs))
+(def content (accessor element :content))
+
+(def content-handler
+  (let [push-content (fn [e c]
+                       (assoc e :content (conj (or (:content e) []) c)))
+        push-chars (fn []
+                     (when (and (= *state* :chars)
+                                (some (complement #(Character/isWhitespace (char %))) (str *sb*)))
+                       (set! *current* (push-content *current* (str *sb*)))))]
+    (new clojure.lang.XMLHandler
+         (proxy [ContentHandler] []
+           (startElement [uri local-name q-name ^Attributes atts]
+             (let [attrs (fn [ret i]
+                           (if (neg? i)
+                             ret
+                             (recur (assoc ret
+                                           (clojure.lang.Keyword/intern (symbol (.getQName atts i)))
+                                           (.getValue atts (int i)))
+                                    (dec i))))
+                   e (struct element
+                             (. clojure.lang.Keyword (intern (symbol q-name)))
+                             (when (pos? (.getLength atts))
+                               (attrs {} (dec (.getLength atts)))))]
+               (push-chars)
+               (set! *stack* (conj *stack* *current*))
+               (set! *current* e)
+               (set! *state* :element))
+             nil)
+           (endElement [uri local-name q-name]
+             (push-chars)
+             (set! *current* (push-content (peek *stack*) *current*))
+             (set! *stack* (pop *stack*))
+             (set! *state* :between)
+             nil)
+           (characters [^chars ch start length]
+             (when-not (= *state* :chars)
+               (set! *sb* (new StringBuilder)))
+             (let [^StringBuilder sb *sb*]
+               (.append sb ch (int start) (int length))
+               (set! *state* :chars))
+             nil)
+           (setDocumentLocator [locator])
+           (startDocument [])
+           (endDocument [])
+           (startPrefixMapping [prefix uri])
+           (endPrefixMapping [prefix])
+           (ignorableWhitespace [ch start length])
+           (processingInstruction [target data])
+           (skippedEntity [name])
+           ))))
+
+(defn startparse-sax [s ch]
+  (.. SAXParserFactory (newInstance) (newSAXParser) (parse s ch)))
+
+(defn parse
+  "Parses and loads the source s, which can be a File, InputStream or
+  String naming a URI. Returns a tree of the xml/element struct-map,
+  which has the keys :tag, :attrs, and :content. and accessor fns tag,
+  attrs, and content. Other parsers can be supplied by passing
+  startparse, a fn taking a source and a ContentHandler and returning
+  a parser"
+  {:added "1.0"}
+  ([s] (parse s startparse-sax))
+  ([s startparse]
+    (binding [*stack* nil
+              *current* (struct element)
+              *state* :between
+              *sb* nil]
+      (startparse s content-handler)
+      ((:content *current*) 0))))
+
+(defn emit-element [e]
+  (if (instance? String e)
+    (println e)
+    (do
+      (print (str "<" (name (:tag e))))
+      (when (:attrs e)
+	(doseq [attr (:attrs e)]
+	  (print (str " " (name (key attr)) "='" (val attr)"'"))))
+      (if (:content e)
+	(do
+	  (println ">")
+	  (doseq [c (:content e)]
+	    (emit-element c))
+	  (println (str "</" (name (:tag e)) ">")))
+	(println "/>")))))
+
+(defn emit [x]
+  (println "<?xml version='1.0' encoding='UTF-8'?>")
+  (emit-element x))
+
+;(export '(tag attrs content parse element emit emit-element))
+
+;(load-file "/Users/rich/dev/clojure/src/xml.clj")
+;(def x (xml/parse "http://arstechnica.com/journals.rssx"))


Update core.cljx

Update core.cljx

--- src/cljx/cats/core.cljx
+++ src/cljx/cats/core.cljx
@@ -27,8 +27,8 @@
   default/effect free context.

   This is multiarity function that with arity pure/1
-  it uses the dynamic scope for resolve the current
-  context. With pure/2, you can force specific context
+  it uses the dynamic scope to resolve the current
+  context. With pure/2, you can force a specific context
   value."
   ([v]
      (p/pure *m-context* v))
@@ -295,29 +295,29 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 (defn get-state
-  "Return State instance with computation that returns
+  "Return a State instance with computation that returns
   the current state."
   []
   (-> (fn [s] (t/pair s s))
       (t/state-t)))

 (defn put-state
-  "Return State instance with computation that replaces
+  "Return a State instance with computation that replaces
   the current state with specified new state."
   [newstate]
   (-> (fn [s] (t/pair s newstate))
       (t/state-t)))

 (defn swap-state
-  "Return State instance with computation that applies
-  specified function to state and return the old state."
+  "Return a State instance with computation that applies the
+  specified function to state and returns the old state."
   [f]
   (-> (fn [s] (t/pair s (f s)))
       (t/state-t)))

 (defn run-state
   "Given a State instance, execute the
-  wrapped computation and return Pair
+  wrapped computation and returns a Pair
   instance with result and new state.

     (def computation (mlet [x (get-state)
@@ -340,7 +340,7 @@
   "Given a State instance, execute the
   wrapped computation and return the resultant
   value, ignoring the state.
-  Shortly, return the first value of pair instance
+  Equivalent to taking the first value of the pair instance
   returned by `run-state` function."
   [state seed]
   (first (run-state state seed)))
@@ -349,7 +349,7 @@
   "Given a State instance, execute the
   wrapped computation and return the resultant
   state.
-  Shortly, return the second value of pair instance
+  Equivalent to taking the second value of the pair instance
   returned by `run-state` function."
   [state seed]
   (second (run-state state seed)))


Update docstrings.

Update docstrings.

--- src/cljx/cats/core.cljx
+++ src/cljx/cats/core.cljx
@@ -34,7 +34,9 @@
 ;; Context Management
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(def ^:dynamic *context* nil)
+(def ^{:dynamic true
+       :no-doc true}
+  *context* nil)

 #+clj
 (defmacro with-monad
@@ -52,7 +54,8 @@
      (binding [*context* ~ctx]
        ~@body)))

-(defn get-current-context
+(defn ^{:no-doc true}
+  get-current-context
   "Get current context or obtain it from
   the provided instance."
   ([] (get-current-context nil))
@@ -86,18 +89,34 @@
   This is multiarity function that with arity pure/1
   it uses the dynamic scope to resolve the current
   context. With `pure/2`, you can force a specific context
-  value."
+  value.
+
+  Example:
+
+      (with-monad either/either-monad
+        (pure 1)
+      ;; => #<Right [1]>
+  "
   ([v] (pure (get-current-context) v))
   ([ctx v] (p/pure ctx v)))

 (defn return
-  "This is a monad version of pure."
+  "This is a monad version of pure and it works
+  identically to it."
   ([v] (return (get-current-context) v))
   ([ctx v] (p/mreturn ctx v)))

 (defn bind
-  "Given a value inside monadic context mv and any function,
-  applies a function to value of mv."
+  "Given a value inside monadic context `mv` and any function,
+  applies a function to value of mv.
+
+      (bind (either/right 1) (fn [v]
+                               (return (inc v))))
+      ;; => #<Right [2]>
+
+  For convenience, you may prefer use a `mlet` macro
+  that add a beautiful, let like syntax for
+  compose operations with `bind` function."
   [mv f]
   (cond
     (satisfies? p/MonadTrans *context*)
@@ -129,7 +148,8 @@
     (mzero)))

 (defn join
-  "Remove one level of monadic structure."
+  "Remove one level of monadic structure.
+  This is same as that `(bind mv identity)`"
   [mv]
   (bind mv identity))

@@ -137,7 +157,8 @@
   "Apply a function f to the value inside functor's fv
   preserving the context type."
   [f fv]
-  (p/fmap (get-current-context fv) f fv))
+  (-> (get-current-context fv)
+      (p/fmap f fv)))

 (defn fapply
   "Given function inside af's conext and value inside
@@ -148,30 +169,24 @@

 (defn when
   "If the expression is true, returns the monadic value.
-
   Otherwise, yields nil in a monadic context."
   ([b mv]
    (when (get-current-context mv) b mv))
   ([ctx b mv]
-   (if b
-     mv
-     (return ctx nil))))
+   (if b mv (return ctx nil))))

 (defn unless
   "If the expression is false, returns the monadic value.
-
   Otherwise, yields nil in a monadic context."
   [b mv]
   (when-not b
     mv))

 (defn lift
-  "Lift a value from the inner monad of a monad transformer into a value
-  of the monad transformer."
-  ([mv]
-   (p/lift *context* mv))
-  ([m mv]
-   (p/lift m mv)))
+  "Lift a value from the inner monad of a monad transformer
+  into a value of the monad transformer."
+  ([mv] (p/lift *context* mv))
+  ([m mv] (p/lift m mv)))

 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Monadic Let Macro
@@ -262,19 +277,16 @@
   "Lifts a function with the given fixed number of arguments to a
   monadic context.

-      (require '[cats.monad.maybe :as maybe])
-      (require '[cats.core :as m])
-
-      (def monad+ (m/lift-m 2 +))
+      (def monad+ (lift-m 2 +))

       (monad+ (maybe/just 1) (maybe/just 2))
-      ;=> <Just [3]>
+      ;; => <Just [3]>

       (monad+ (maybe/just 1) (maybe/nothing))
-      ;=> <Nothing>
+      ;; => <Nothing>

       (monad+ [0 2 4] [1 2])
-      ;=> [1 2 3 4 5 6]
+      ;; => [1 2 3 4 5 6]
   "
   [n f]
   (let [val-syms (repeatedly n gensym)
@@ -292,14 +304,11 @@
   "Given a non-empty collection of monadic values, collect
   their values in a vector returned in the monadic context.

-      (require '[cats.monad.maybe :as maybe])
-      (require '[cats.core :as m])
-
-      (m/sequence [(maybe/just 2) (maybe/just 3)])
-      ;=> <Just [[2, 3]]>
-
-      (m/sequence [(maybe/nothing) (maybe/just 3)])
-      ;=> <Nothing>
+      (sequence [(maybe/just 2) (maybe/just 3)])
+      ;; => <Just [[2, 3]]>
+
+      (sequence [(maybe/nothing) (maybe/just 3)])
+      ;; => <Nothing>
   "
   [mvs]
   {:pre [(not-empty mvs)]}
@@ -336,18 +345,19 @@
 (defn forseq
   "Same as mapseq but with the arguments in reverse order.

-      (require '[cats.monad.maybe :as maybe])
-      (require '[cats.core :as m])
+  Let se a little example:

       (m/forseq [2 3] maybe/just)
-      ;=> <Just [[2 3]]>
+      ;; => <Just [[2 3]]>
+
+  Yet an other example that fails:

       (m/forseq [1 2]
                 (fn [v]
                   (if (odd? v)
                     (maybe/just v)
                     (maybe/nothing))))
-      ;=> <Nothing>
+      ;; => <Nothing>
   "
   [vs mf]
   (mapseq mf vs))
@@ -393,11 +403,13 @@
    (reduce fapply af (cons av avs))))

 (defn >>=
-  "Performs a Haskell-style left-associative bind.
-
-  Example:
-    (>>= (just 1) (comp just inc) (comp just inc))
-    ;=> #<Just [3]>
+  "Performs a Haskell-style left-associative
+  bind.
+
+  Let see it in action:
+
+      (>>= (just 1) (comp just inc) (comp just inc))
+      ;; => #<Just [3]>
   "
   ([mv f]
    (bind mv f))


Config module

Config module

error: pathspec 'src/clouseau/config.clj' did not match any file(s) known to git

--- src/clouseau/config.clj
+++ src/clouseau/config.clj
@@ -0,0 +1,39 @@
+;
+;  (C) Copyright 2016  Pavel Tisnovsky
+;
+;  All rights reserved. This program and the accompanying materials
+;  are made available under the terms of the Eclipse Public License v1.0
+;  which accompanies this distribution, and is available at
+;  http://www.eclipse.org/legal/epl-v10.html
+;
+;  Contributors:
+;      Pavel Tisnovsky
+;
+
+(ns clouseau.config)
+
+(require '[clojure.pprint :as pprint])
+
+(require '[clojure-ini.core :as clojure-ini])
+
+(defn parse-int
+    "Parse the given string as an integer number."
+    [string]
+    (java.lang.Integer/parseInt string))
+
+(defn update-server-configuration
+    "Update server configuration from the loaded data."
+    [configuration]
+    (update-in configuration [:server :port] parse-int))
+
+(defn load-configuration
+    "Load configuration from the provided INI file."
+    [ini-file-name]
+    (-> (clojure-ini/read-ini ini-file-name :keywordize? true)
+        update-server-configuration))
+
+(defn print-configuration
+    "Print actual configuration to the output."
+    [configuration]
+    (pprint/pprint configuration))
+


Adding more conversion functionality

Adding more conversion functionality

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/xcthulhu/clj-bitauth.git/'


heapsort

heapsort

error: pathspec 'src/xl/heapsort.clj' did not match any file(s) known to git

--- src/xl/heapsort.clj
+++ src/xl/heapsort.clj
@@ -0,0 +1,111 @@
+(ns xl.heapsort
+  (:require [clojure.spec :as s])
+  )
+
+(defn- swap-val [^doubles ns a b]
+  (let [tmp (nth ns a)]
+    (aset ns a (nth ns b))
+    (aset ns b tmp)
+    )
+  )
+
+(defn sift-down [^doubles ns start end]
+  (loop [curr start]
+    (when (< curr end)
+      (let [left (int (dec (* (inc curr) 2)))
+            ]
+        (when (and (< left end) (< (nth ns left) (nth ns curr)))
+          (swap-val ns curr left)
+          (sift-down ns left end)
+          )
+        )
+      (let [right (int (* (inc curr) 2))
+            ]
+        (when (and (< right end) (< (nth ns right) (nth ns curr)))
+          (swap-val ns curr right)
+          (sift-down ns right end)
+          )
+        )
+      )
+    )
+  )
+
+(defn heapify [^doubles ns]
+  (let [len (count ns)]
+    (loop [curr (dec (int (Math/ceil (/ len 2))))]
+      (when-not (neg? curr)
+        (sift-down ns curr len)
+        (recur (dec curr))
+        )
+      )
+    )
+  )
+
+(defn- internal-heap-sort [^doubles ns]
+  (heapify ns)
+  (loop [end (dec (count ns))]
+    (when (pos? end)
+      (swap-val ns 0 end)
+      (sift-down ns 0 end)
+      (recur (dec end))
+      )
+    )
+  )
+
+(defn heap-sort [xs0]
+  (if (<= (count xs0) 1)
+    xs0
+    (let [xs (double-array xs0)]
+      (internal-heap-sort xs)
+      (seq xs)
+      )
+    )
+  )
+
+(doseq [ns [
+            [1.0 -1.0 1.0 -1.0 1.0]
+            ]]
+  (println "ns: " (seq ns))
+  (println "sorted: " (heap-sort ns))
+  )
+
+(defn ordered? [xs]
+  (if (<= (count xs) 1)
+    true
+    (let [[x & rest] xs]
+      (and (ordered? rest) (>= x (first rest)))
+      )
+    )
+  )
+
+(defn- remove-first [xs y]
+  (if (empty? xs)
+    xs
+    (let [[x & rest] xs]
+      (if (= x y)
+        rest
+        (cons x (remove-first rest y))
+        )
+      )
+    )
+  )
+
+(defn same-items? [xs ys]
+  (and
+    (= (count xs) (count ys))
+    (or
+      (empty? xs)
+      (let [[x & rest-xs] xs]
+        (and (some #{x} ys) (same-items? rest-xs (remove-first ys x)))
+        )
+      )
+    )
+  )
+
+(s/fdef heap-sort
+        :args (s/cat :ns (s/coll-of (s/double-in :NaN? false :infinite? false)))
+        :ret (s/coll-of  (s/double-in :NaN? false :infinite? false))
+        :fn (s/and
+              #(ordered? (:ret %))
+              #(same-items? (-> % :args :ns) (:ret %))
+              ))


[WM] use different address in handlers-test

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/voter-registration-works.git/'


cleanup

cleanup

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/tobiasbayer/lambdacd.git/'


Redefine operators earlier

Redefine operators earlier

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/michaelsbradleyjr/shen.clj.git/'


Should be ns-resolve

Should be ns-resolve


Test for resembling Java OrderServiceTest. Using map and pmap.

error: pathspec 'clojure-functional/src/test/clojure/no/knowit/clojure_functional/order_service.clj' did not match any file(s) known to git

--- clojure-functional/src/test/clojure/no/knowit/clojure_functional/order_service.clj
+++ clojure-functional/src/test/clojure/no/knowit/clojure_functional/order_service.clj
@@ -0,0 +1,34 @@
+(ns no.knowit.clojure_functional.order-service
+  (:use [clojure.test])
+  (:import no.knowit.java_functional.product.Product)
+  (:import [no.knowit.java_functional.order TrainJourney Order])
+  (:import [org.joda.time DateTime]))
+
+
+(defn create-order [train-journey]
+  (do (Thread/sleep 200)
+    (new Order train-journey 123.0)))
+
+(defn create-order-coll [itinerary-coll]
+  (map create-order itinerary-coll))
+
+(defn create-order-coll-par [itinerary-coll]
+  (pmap create-order itinerary-coll))
+
+(defn create-itineraries []
+  (let [from "OSLO S"
+        to "BERGEN"
+        departure-time (new DateTime)]
+  (repeatedly 5
+    #(new TrainJourney from to departure-time
+       (.plusHours departure-time 2)))))
+
+(deftest test-creating-orders
+  (let [itineraries (create-itineraries)
+        start (System/currentTimeMillis)
+        result (doall (create-order-coll-par itineraries))
+        stop (- (System/currentTimeMillis) start)]
+    (is (= 5 (count result)))
+    (is (< stop 400))))
+
+(run-tests)


Shared rand-nth-weighted

Shared rand-nth-weighted

error: pathspec 'src/cljc/mokkameister/random.cljc' did not match any file(s) known to git

--- src/cljc/mokkameister/random.cljc
+++ src/cljc/mokkameister/random.cljc
@@ -0,0 +1,20 @@
+(ns mokkameister.random)
+
+(defn rand-nth-weighted
+  "Return a random element from the weighted collection.
+
+  A weighted collection can be any seq of [choice, weight] elements.  The
+  weights can be arbitrary numbers -- they do not need to add up to anything
+  specific.
+
+  Examples:
+  (rand-nth-weighted [[:a 0.50] [:b 0.20] [:c 0.30]])
+  (rand-nth-weighted {:a 10 :b 200})
+  "
+  [coll]
+  (let [total (reduce + (map second coll))]
+    (loop [i (rand total)
+           [[choice weight] & remaining] (seq coll)]
+      (if (>= weight i)
+        choice
+        (recur (- i weight) remaining)))))


Cosmetic and docstrings improvements on identity monad ns.

--- src/cljx/cats/monad/identity.cljx
+++ src/cljx/cats/monad/identity.cljx
@@ -74,7 +74,7 @@
 (alter-meta! #'->Identity assoc :private true)

 (defn identity
-  "Default constructor for identity type."
+  "The Identity type constructor."
   [v]
   (Identity. v))

@@ -82,7 +82,8 @@
 ;; Monad definition
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(def identity-monad
+(def ^{:no-doc true}
+  identity-monad
   (reify
     proto/Functor
     (fmap [_ f iv]
@@ -106,13 +107,13 @@
 ;; Monad transformer definition
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

-(defn identity-transformer [inner-monad]
+(defn identity-transformer
+  "The Identity transformer constructor."
+  [inner-monad]
   (reify
     proto/Monad
     (mreturn [_ v]
       (identity (proto/mreturn inner-monad v)))

     (mbind [_ mv f]
-      nil)
-
-))
+      nil)))


fix grammatical error

fix grammatical error

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/starcity-properties/odin.git/'


fix mistake: make it possible to use other DBs than _system in the ...-by-example methods in document ns

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/colophon/clarango.git/'


naive intersection

naive intersection

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/yokalona/threen.git/'


missing goog.dom require

missing goog.dom require

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/modnakasta/weasel.git/'


Simplify :document-date handling

Simplify :document-date handling

--- src/pepa/model.clj
+++ src/pepa/model.clj
@@ -121,11 +121,13 @@
                                        ORDER BY dt.seq"
                                  ids :document)]
         (map (fn [{:keys [id] :as document}]
-               (assoc document
-                      :pages (->> (vec (get pages id))
-                                  (mapv #(update-in % [:dpi] pg-array->set)))
-                      :tags (mapv :name (get tags id))))
-             (map #(clojure.set/rename-keys %1 {:document_date :document-date}) documents))))))
+               (-> document
+                   (assoc :pages (->> (vec (get pages id))
+                                      (mapv #(update-in % [:dpi] pg-array->set)))
+                          :tags (mapv :name (get tags id))
+                          :document-date (:document_date document))
+                   (dissoc :document_date)))
+             documents)))))

 (defn get-document [db id]
   (first (get-documents db [id])))
@@ -142,15 +144,11 @@
                condition)
           params)))

-(defn query-documents
-  ([db]
-   (map #(clojure.set/rename-keys %1 {:document_date :document-date})
-        (db/query db documents-base-query)))
-  ([db query]
-   (if (nil? query)
-     (query-documents db)
-     (map #(clojure.set/rename-keys %1 {:document_date :document-date})
-          (db/query db (documents-query query))))))
+(defn query-documents [db & [query]]
+  (map #(set/rename-keys %1 {:document_date :document-date})
+       (if (nil? query)
+         (db/query db documents-base-query)
+         (db/query db (documents-query query)))))

 (defn document-file
   "Returns the id of the file associated to document with ID. Might be
@@ -250,12 +248,10 @@
             removed-tags (set removed-tags)
             props (->
                    props
-                   (clojure.set/rename-keys {:document-date :document_date})
-                   (update-in [:document_date] (fn [date]
-                                                 (when date
-                                                   (->> date
-                                                        (.getTime)
-                                                        (Date.))))))
+                   (update :document-date
+                           (fn [date]
+                             (some-> date (.getTime) (Date.))))
+                   (set/rename-keys {:document-date :document_date}))
             ;; Subtract removed-tags from added-tags so we don't
             ;; create tags which will be removed instantly
             added-tags (set/difference added-tags removed-tags)]


Add first version of a standard test runner

When finished this test runner will only require that each transit
implementation have a script in bin/roundtrip which can read a transit
string from standard in, roundtrip it, and write the result to standard
out.

It will feed all of the sample files as well as generated edn data.

error: pathspec 'test/transit/verify.clj' did not match any file(s) known to git

--- test/transit/verify.clj
+++ test/transit/verify.clj
@@ -0,0 +1,119 @@
+(ns transit.verify
+  (:require [transit.read :as r]
+            [transit.write :as w]
+            [clojure.java.io :as io])
+  (:import [java.io PrintStream ByteArrayOutputStream ByteArrayInputStream]))
+
+;; TODO: dynamically find `bin/roundtrip` commands
+(def command "../transit-java/bin/roundtrip")
+
+(defn write-transit [o]
+  (let [out (ByteArrayOutputStream.)
+        w (w/writer out :json)]
+    (w/write w o)
+    (.toString out)))
+
+(defn read-transit [t]
+  (let [in (ByteArrayInputStream. (.getBytes t))
+        r (r/reader in :json)]
+    (r/read r)))
+
+(defn start-process [command]
+  (let [p (.start (ProcessBuilder. [command]))
+        out (PrintStream. (.getOutputStream p))
+        in (.getInputStream p)]
+    {:out out :in in :p p}))
+
+(defn stop-process [proc]
+  (.write (:out proc) 3) ;; send Ctrl+C
+  (.flush (:out proc))
+  (.destroy (:p proc)))
+
+(defn write-to-stream [proc transit-data]
+  (.print (:out proc) transit-data)
+  (.flush (:out proc)))
+
+(defn continue? [prev c counter open close]
+  (cond (and (not= prev \^) (= c open)) inc
+        (and (not= prev \^) (= c close)) (when (pos? (dec counter)) dec)
+        :else identity))
+
+(defn read-from-stream [proc]
+  (loop [state :wait
+         counter 0
+         prev nil
+         s nil]
+    (let [c (.read (:in proc))]
+    (if (== c -1)
+      s
+      (let [c (char c)]
+        (case state
+          :wait (cond (= c \[) (recur :array (inc counter) c (str s c))
+                      (= c \{) (recur :object (inc counter) c (str s c))
+                      :else (recur state counter c s))
+          :array (if-let [f (continue? prev c counter \[ \])]
+                   (recur state (f counter) c (str s c))
+                   (str s c))
+          :object (if-let [f (continue? prev c counter \{ \})]
+                    (recur state (f counter) c (str s c))
+                    (str s c))))))))
+
+(defn roundtrip-transit-string [proc transit-out compare-transit?]
+  (write-to-stream proc transit-out)
+  ;; TODO: need a timeout here so this doesn't block forever
+  (let [transit-in (read-from-stream proc)
+        data-out (read-transit transit-out)
+        data-in (read-transit transit-in)]
+    {:transit-expected transit-out
+     :transit-actual transit-in
+     :data-expected data-out
+     :data-actual data-in
+     ;; only checks the top level type
+     :status (if (and (= (type data-out) (type data-in))
+                      (= data-out data-in)
+                      (or (not compare-transit?) (= (count transit-out) (count transit-in))))
+               :success
+               :error)}))
+
+(defn roundtrip-edn [proc edn compare-transit?]
+  (let [transit-out (write-transit edn)
+        result (roundtrip-transit-string proc transit-out compare-transit?)]
+    (if (not= edn (:data-actual result) (:data-expected result))
+      (assoc result :status :warning)
+      result)))
+
+(defn test-sample-files
+  ([] (test-sample-files false))
+  ([compare-transit?]
+     (let [files (filter #(and (.isFile %) (.endsWith (.getName %) ".json"))
+                         (file-seq (io/file "../transit/simple-examples")))
+           proc (start-process command)]
+       (println "Testing against" (count files) "sample files.")
+       (doseq [file files]
+         (let [result (roundtrip-transit-string proc (slurp file) compare-transit?)]
+           (when (contains? #{:warning :error} (:status result))
+             (do (println (.getName file) (:status result))
+                 (println "Expected:" (:transit-expected result))
+                 (println "Actual:  " (:transit-actual result))))))
+       (stop-process proc))))
+
+(defn test-edn
+  ([] (test-edn false))
+  ([compare-transit?]
+     ;; TODO: use generators
+     (let [forms [true false :a :foo :foobar 42 'foo (java.util.Date.) 1/3 \t "hello" "~hello"
+                  [1 2 3] `(7 23 5) {:foo :bar} #{:a :b :c}]
+           proc (start-process command)]
+       (println "Testing against" (count forms) "forms.")
+       (doseq [form forms]
+         (let [result (roundtrip-edn proc form compare-transit?)]
+           (when (= :warning (:status result))
+             (do (println (:status result))
+                 (println "Expected:" (pr-str form))
+                 (println "Actual:  " (pr-str (:data-actual result)))))
+           (when (= :error (:status result))
+             (do (println (:status result))
+                 (println (pr-str form))
+                 (println "Expected:" (:transit-expected result))
+                 (println "Actual:  " (:transit-actual result))))))
+       (stop-process proc))))


Module to read configuration

Module to read configuration

error: pathspec 'src/clj_mrazik/config.clj' did not match any file(s) known to git

--- src/clj_mrazik/config.clj
+++ src/clj_mrazik/config.clj
@@ -0,0 +1,25 @@
+(ns clj-mrazik.config)
+
+(require '[clojure-ini.core :as clojure-ini])
+
+(defn parse-int
+    [string]
+    (java.lang.Integer/parseInt string))
+
+(defn parse-hh-mm-time-as-minutes
+    [string]
+    (let [time (-> (java.text.SimpleDateFormat. "HH:mm")
+               (.parse string))]
+         (+ (.getMinutes time)
+            (* 60 (.getHours time)))))
+
+(defn load-configuration
+    "Load configuration from the provided INI file."
+    [ini-file-name]
+    (-> (clojure-ini/read-ini ini-file-name :keywordize? true)
+        (update-in [:server :port] parse-int)
+        (update-in [:bot :start]     parse-hh-mm-time-as-minutes)
+        (update-in [:bot :end]       parse-hh-mm-time-as-minutes)
+        (update-in [:bot :frequency] parse-hh-mm-time-as-minutes)
+        (update-in [:bot :duration]  parse-hh-mm-time-as-minutes)))
+


Add a basic test to ensure libssh2 is JNA-ed properly.

error: pathspec 'test/clj_libssh2/test_libssh2.clj' did not match any file(s) known to git

--- test/clj_libssh2/test_libssh2.clj
+++ test/clj_libssh2/test_libssh2.clj
@@ -0,0 +1,7 @@
+(ns clj-libssh2.test-libssh2
+  (:require [clojure.test :refer :all]
+            [clj-libssh2.libssh2 :as libssh2]))
+
+(deftest check-libssh2-version-is-ok
+  "This shoudln't change by surprise!"
+  (is (= "1.6.0" (libssh2/version))))


hiccup-util.core

hiccup-util.core

error: pathspec 'src/hiccup_util/core.cljs' did not match any file(s) known to git

--- src/hiccup_util/core.cljs
+++ src/hiccup_util/core.cljs
@@ -0,0 +1,10 @@
+(ns hiccup-util.core)
+
+(defn classnames [classes-map]
+  (->>
+    classes-map
+    (filter #(true? (second %)))
+    (map first)
+    (map name)
+    (interpose " ")
+    (apply str)))


fix "can't infer SQL type" error

fix "can't infer SQL type" error

--- src/metabase/driver/generic_sql/query_processor.clj
+++ src/metabase/driver/generic_sql/query_processor.clj
@@ -150,7 +150,8 @@
     [_ field-id & _] {(field-id->kw field-id)
                       ;; If the field in question is a date field we need to cast the YYYY-MM-DD string that comes back from the UI to a SQL date
                       (let [cast-value-if-needed (fn [v]
-                                                   (cond (= (type v) java.sql.Date)           `(raw ~(format "CAST('%s' AS DATE)" (.toString ^java.sql.Date v)))
+                                                   (cond (or (= (type v) java.sql.Date)
+                                                             (= (type v) java.util.Date))    `(raw ~(format "CAST('%s' AS DATE)" (.toString ^java.sql.Date v)))
                                                          (not (string? v))                    v
                                                          (date-field-id? field-id)            (u/parse-date-yyyy-mm-dd v)
                                                          (= (field-id->special-type field-id)


standardize arg names

standardize arg names

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/notification-works.git/'


add macro unless

add macro unless

error: pathspec 'clojure/unless.clj' did not match any file(s) known to git

--- clojure/unless.clj
+++ clojure/unless.clj
@@ -0,0 +1,4 @@
+(defmacro unless [test ifnil iftrue]
+  `(if ~test ~iftrue ~ifnil))
+
+(unless false (println "TRUE") (println "FALSE"))


Add sample scripts

Add sample scripts

error: pathspec 'play/factorial.clj' did not match any file(s) known to git

--- play/factorial.clj
+++ play/factorial.clj
@@ -0,0 +1,12 @@
+(defn fac
+  [n]
+  (if (zero? n)
+    1
+    (* n (fac (- n 1)))))
+
+(defn fac1
+  [n]
+  (loop [res 1 x n]
+    (if (zero? x)
+      res
+      (recur (* res x) (- x 1)))))


fixes

fixes

and getting the compiler to play nice

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Arctice/anime-birb-uk.git/'


Update fac.clj

Update fac.clj

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/hellopy/SOME.git/'


add o++

add o++

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/carolove/clojure-ring-app.git/'


Add stub for nth-prime

Add stub for nth-prime

error: pathspec 'exercises/nth-prime/src/nth_prime.clj' did not match any file(s) known to git

--- exercises/nth-prime/src/nth_prime.clj
+++ exercises/nth-prime/src/nth_prime.clj
@@ -0,0 +1,5 @@
+(ns nth-prime)
+
+(defn nth-prime [] ;; <- arglist goes here
+  ;; your code goes here
+  )


Make an if-statement

Make an if-statement

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/kkroening/jackal.git/'


:art: Minor refactoring

:art: Minor refactoring

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/maoo/bot-unfurl.git/'


Minor test reformatting

Minor test reformatting


add utils tests

add utils tests

error: pathspec 'dada2-core/src/test/clojure/org/dada2/test_utils.clj' did not match any file(s) known to git

--- dada2-core/src/test/clojure/org/dada2/test_utils.clj
+++ dada2-core/src/test/clojure/org/dada2/test_utils.clj
@@ -0,0 +1,18 @@
+(ns org.dada2.test-utils
+ (:use
+  [clojure test]
+  [clojure.tools logging]
+  [org.dada2 utils]))
+
+(deftest test-swap*!
+  (let [old-state 1
+	state (atom old-state)
+	old-increment 2
+	[new-state new-increment] (swap*!
+				   state
+				   (fn [state increment] [(+ state increment) increment])
+				   old-increment)]
+    (is (= new-state @state))
+    (is (= new-state (+ old-state old-increment)))
+    (is (= new-increment old-increment))
+    ))


actually, more than 10 times is probably not great regardless

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/election-notification-works.git/'


Mild cleanup.

Mild cleanup.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/couragelabs/coachbot.git/'


change transition type based on selected community

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/starcity-properties/odin.git/'


explicitly select keys to update

explicitly select keys to update


Clairify bind

Clairify bind

--- src/cljx/cats/core.cljx
+++ src/cljx/cats/core.cljx
@@ -92,12 +92,11 @@
      (with-monad (p/get-context mv)
        (p/mbind *context* mv f))

-   (or (satisfies? p/MonadTrans *context*)
-       (not (satisfies? p/Context mv)))
+   (satisfies? p/MonadTrans *context*)
      (p/mbind *context* mv f)

    :else
-     (p/mbind (p/get-context mv) mv f)
+     (p/mbind (get-current-context-or mv) mv f)
 ))

 (defn mzero


Add fmap/1 arity (auto curry)

Add fmap/1 arity (auto curry)

--- src/cljx/cats/core.cljx
+++ src/cljx/cats/core.cljx
@@ -78,8 +78,11 @@

 (defn <$>
   "Alias of fmap."
-  [f fv]
-  (p/fmap fv f))
+  ([f]
+     (fn [fv]
+       (p/fmap fv f)))
+  ([f fv]
+     (p/fmap fv f)))

 (defn <*>
   "Performs a Haskell-style left-associative fapply."


Tests for schema versioning handling

Tests for schema versioning handling

error: pathspec 'test/photon/current/schema_test.clj' did not match any file(s) known to git

--- test/photon/current/schema_test.clj
+++ test/photon/current/schema_test.clj
@@ -0,0 +1,69 @@
+(ns photon.current.schema-test
+  (:require [muon-clojure.client :as cl]
+            [photon.muon :as muon]
+            [photon.config :as conf]
+            [clojure.tools.logging :as log]
+            [clojure.core.async :refer [<!!]]
+            [com.stuartsierra.component :as component]
+            [photon.current.common :refer :all])
+  (:use midje.sweet))
+
+(let [uuid (java.util.UUID/randomUUID)
+      ms (new-server uuid)
+      s-name (str "photon-integration-test-" uuid)
+      url-req (str "request://" s-name)
+      url-str (str "stream://" s-name)
+      m (cl/muon-client :local (str "client-" uuid)
+                        "client" "test")
+      spn (cl/with-muon m
+            (cl/request! (str url-req "/projection")
+                         {:projection-name "idontexist"}))
+      sp (cl/with-muon m
+           (cl/request! (str url-req "/projection")
+                        {:projection-name "__streams__"}))]
+  (fact "The streams projection indicates 0 events processed"
+        (:processed sp) => 0.0)
+  (post-one-event m s-name)
+  (let [new-sp (cl/with-muon m
+                 (cl/request! (str url-req "/projection")
+                              {:projection-name "__streams__"}))]
+    (fact "Now there is one event processed"
+          (:processed new-sp) => 1.0))
+  (let [res (cl/with-muon m
+              (cl/request! (str url-req "/projection")
+                           {:projection-name "__streams__"}))]
+    (fact "Only __unversioned__ schema"
+          (into #{} (keys (:schemas (:chatter (:current-value res)))))
+          => #{:__unversioned__})
+    (fact "Schema parts are correct"
+          (-> res :current-value :chatter :schemas :__unversioned__
+              :schema :m ((keyword "[:service-id]")) :type)
+          (-> res :current-value :chatter :schemas :__unversioned__
+              :schema :m ((keyword "[:service-id]")) :mode) => "required")
+    (post-one-event m s-name "0.0.1")
+    (clojure.pprint/pprint (:schemas (:chatter (:current-value res))))
+    (let [res (cl/with-muon m
+                (cl/request! (str url-req "/projection")
+                             {:projection-name "__streams__"}))]
+      (fact "Not only __unversioned__ schema"
+            (into #{} (keys (:schemas (:chatter (:current-value res)))))
+            =not=> #{:__unversioned__})
+      (fact "New version in schemas"
+            (contains? (:schemas (:chatter (:current-value res)))
+                       :0.0.1)
+            => truthy)
+      (fact "Schema parts for unversioned are correct"
+            (-> res :current-value :chatter :schemas :__unversioned__
+                :schema :m ((keyword "[:service-id]")) :count) => 1.0
+            (-> res :current-value :chatter :schemas :__unversioned__
+                :schema :m ((keyword "[:service-id]")) :type) => "s/Str"
+            (-> res :current-value :chatter :schemas :__unversioned__
+                :schema :m ((keyword "[:service-id]")) :mode) => "required")
+      (fact "Schema parts for 0.0.1 are correct"
+            (-> res :current-value :chatter :schemas :0.0.1
+                :schema :m ((keyword "[:service-id]")) :count) => 1.0
+            (-> res :current-value :chatter :schemas :0.0.1
+                :schema :m ((keyword "[:service-id]")) :type) => "s/Str"
+            (-> res :current-value :chatter :schemas :0.0.1
+                :schema :m ((keyword "[:service-id]")) :mode) => "required")))
+  (component/stop ms))


adds notification for user feedback on deletion


This is just absurd. This data is utter garbage. But... through sheer violence more of it is getting successfully parsed.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/mtravers/incidents.git/'


Better name.

Better name.


Add beer_song.clj stub

Add beer_song.clj stub

error: pathspec 'exercises/beer-song/src/beer_song.clj' did not match any file(s) known to git

--- exercises/beer-song/src/beer_song.clj
+++ exercises/beer-song/src/beer_song.clj
@@ -0,0 +1,9 @@
+(ns beer-song)
+
+;; implement two functions: one gives you a single verse, one gives you the entire song or a part of it
+
+(defn verse [n])
+
+(defn sing
+  ([from])
+  ([from to])


Skeleton CodecBlobStore implementation.

Skeleton CodecBlobStore implementation.

error: pathspec 'src/vault/blob/store/codec.clj' did not match any file(s) known to git

--- src/vault/blob/store/codec.clj
+++ src/vault/blob/store/codec.clj
@@ -0,0 +1,43 @@
+(ns vault.blob.store.codec
+  (:require
+    [vault.blob.core :as blob :refer [BlobStore]]))
+
+
+(defrecord CodecBlobStore
+  [store encoders decoders]
+
+  BlobStore
+
+  (enumerate [this opts]
+    (blob/enumerate store opts))
+
+
+  (stat [this id]
+    (blob/stat store id))
+
+
+  (get* [this id]
+    (when-let [blob (blob/get* store id)]
+      (reduce #(or (%2 %1) %1) blob decoders)))
+
+
+  (put! [this blob]
+    (when-not (empty? (:content blob))
+      (->>
+        encoders
+        (reduce #(or (%2 %1) %1) blob)
+        (blob/put! store)))))
+
+
+(defn codec-store
+  "Wraps a blob store with encoders and decoders."
+  [store encoders decoders]
+  {:pre [(satisfies? BlobStore store)]}
+  (let [vectorize #(cond
+                     (nil? %) []
+                     (vector? %) %
+                     :else (vector %))]
+    (CodecBlobStore.
+      store
+      (vectorize encoders)
+      (vectorize decoders))))


remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/sharkspeed/dororis.git/'


more test

more test

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/burner-432e4b5d76/scrapefruit.git/'


setting back analysis

setting back analysis

--- src/es/systems.clj
+++ src/es/systems.clj
@@ -30,7 +30,7 @@
   {:system
     {:properties {
       :owner {:type "string" }
-      :env {:type "string" :index "not_analyzed"}
+      :env {:type "string"}
       :type {:type "string"}
      }
     }
@@ -83,7 +83,7 @@
 (defn- query-for [username q]
   (let [{:keys [envs username] :as user} (p/get-user! username)]
     (if (su? user)
-      (let [ts (mapv #(hash-map :term {"env" (str %)}) envs)]
+      (let [ts (mapv #(hash-map :term {:env (name %)}) envs)]
         (-> q (update-in [:bool :should] (fn [v] (into v ts))) (assoc-in [:bool :minimum_should_match] 1)))
       (update-in q [:bool :must] (fn [v] (into v {:term {"owner" username}}))))))


Update to the latest handle-errors

Update to the latest handle-errors

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/democracyworks/vote-by-mail-works.git/'


simplify the implementation of query expander a bit

--- src/metabase/driver/query_processor/expand.clj
+++ src/metabase/driver/query_processor/expand.clj
@@ -50,8 +50,8 @@
          parse-breakout
          parse-fields
          parse-filter
-         parse-order-by
-         with-resolved-fields)
+         parse-order-by)
+

 ;; ## -------------------- Protocols --------------------

@@ -70,7 +70,7 @@
   IResolveField {:resolve-field (constantly nil)})

-;; ## -------------------- Public Interface --------------------
+;; ## -------------------- Parser --------------------

 (defn- parse [query-dict]
   (update-in query-dict [:query] #(-<> (assoc %
@@ -82,10 +82,27 @@
                                        (set/rename-keys <> {:order_by :order-by})
                                        (m/filter-vals identity <>))))

+(def ^:private ^:dynamic *field-ids*
+  "Bound to an atom containing a set when a parsing function is ran"
+  nil)
+
+
+;; ## -------------------- Public Interface --------------------
+
 (defn expand
   "Expand a query-dict."
   [query-dict]
-  (with-resolved-fields parse query-dict))
+  (binding [*field-ids* (atom #{})]
+    (when-let [parsed-form (parse query-dict)]
+      (if-not (seq @*field-ids*) parsed-form ; No need to do a DB call or walk parsed-form if we didn't see any Field IDs
+              (let [fields (->> (sel :many :id->fields [field/Field :name :base_type :special_type] :id [in @*field-ids*])
+                                (m/map-vals #(set/rename-keys % {:id           :field-id
+                                                                 :name         :field-name
+                                                                 :special_type :special-type
+                                                                 :base_type    :base-type})))]
+                ;; This is performed depth-first so we don't end up walking the newly-created Field/Value objects
+                ;; they may have nil values; this was we don't have to write an implementation of resolve-field for nil
+                (walk/postwalk #(resolve-field % fields) parsed-form))))))

 ;; ## -------------------- Field + Value --------------------
@@ -140,10 +157,6 @@
         parse-value
         map->Value)))

-(def ^:private ^:dynamic *field-ids*
-  "Bound to an atom containing a set when a parsing function is ran"
-  nil)
-
 (defn- ph
   "Create a new placeholder object for a Field ID or value.
    If `*field-ids*` is bound, "
@@ -153,26 +166,6 @@
    (->FieldPlaceholder field-id))
   ([field-id value]
    (->ValuePlaceholder field-id value)))
-
-
-;; ## -------------------- Field Resolution --------------------
-
-(defn- with-resolved-fields
-  "Call (PARSER-FN FORM), collecting the `Field` IDs encountered; then fetch the relevant Fields
-   and walk the parsed form, calling `resolve-field` on each element."
-  [parser-fn form]
-  (when form
-    (binding [*field-ids* (atom #{})]
-      (when-let [parsed-form (parser-fn form)]
-        (if-not (seq @*field-ids*) parsed-form ; No need to do a DB call or walk parsed-form if we didn't see any Field IDs
-                (let [fields (->> (sel :many :id->fields [field/Field :name :base_type :special_type] :id [in @*field-ids*])
-                                  (m/map-vals #(set/rename-keys % {:id           :field-id
-                                                                   :name         :field-name
-                                                                   :special_type :special-type
-                                                                   :base_type    :base-type})))]
-                  ;; This is performed depth-first so we don't end up walking the newly-created Field/Value objects
-                  ;; they may have nil values; this was we don't have to write an implementation of resolve-field for nil
-                  (walk/postwalk #(resolve-field % fields) parsed-form)))))))

 ;; # ======================================== CLAUSE DEFINITIONS ========================================


removing some unnecessary comments.

removing some unnecessary comments.

--- test/metabase/models/field_test.clj
+++ test/metabase/models/field_test.clj
@@ -58,9 +58,6 @@
                                                :special_type :country
                                                :field_type   :dimension}))

-;; NOT field_type = senstive
-;; NOT base_type = date, datetime, time
-;; (required) special_type = category, city, state, country OR base_type = boolean

 ;; Check that setting a Field's special_type to :category will cause a corresponding FieldValues to be created asynchronously
 (expect


Removing the CLisp scaffoliding

Removing the CLisp scaffoliding

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/michaelsbradleyjr/shen.clj.git/'