Fork me on GitHub

I've written a function that takes a lazy sequence and returns a lazy sequence of the partial sums (i.e. the accumulated sum of all terms to that point). I came up with this but it feels like there's a more direct way to do it. Am I missing something?

(defn partial-sums
  ([nums] (partial-sums 0 nums))
  ([acc [fst & rst]]
   (let [new-acc ((fnil + 0) fst acc)]
     (cons new-acc (lazy-seq (partial-sums new-acc rst))))))


(reductions + [1 2 3 4])

nice 1
❤️ 1

Perfect, thanks!

Tim Robinson13:02:11

Can anyone explain the difference between and and when ? they sound like different concepts but seem to do the the same thing (i.e. evaluate and return the second arg only if the first one is true)


Not quite. and is a “short-circuiting” boolean AND operation that returns “truthy” if all its arguments are truthy, and when more like an if without an else--if the first argument to when is true, it evaluates all the rest of its arguments regardless of whether or not they return a truthy value. (Where “truthy” means any non-nil value).


So if you have (and a b c d e) and a and b are true and c is nil, and will return false without ever evaluating d and e. (when a b c d e) will evaluate all 5 arguments, as long as a returns a truthy value.


A slightly more interesting example:

(and true 1 "ok" nil (throw (Exception. "boom")))
=> nil
(when true 1 "ok" nil (throw (Exception. "boom")))
Execution error at user/eval36922 (form-init10506123581459132295.clj:1).

Tim Robinson13:02:24

yes good point, I was only thinking about the simple case of (when a b)

Tim Robinson13:02:32

Also (and false x) returns false whereas (when false x) returns nil (though that often wouldn't matter)



(and false true)
=> false
(and nil true)
=> nil


So technically if and finds a falsy value, it immediately returns the falsy value and does not evaluate any further args.


I got a strange error: I was running something in a loop for about a day with a Thread/sleep in it. It was working great, but then it randomly crashed

 "Syntax error reading source at (tempplot/core.clj:21:1).\nEOF while reading, starting at line 16\n",
But the file never changed, how in the world is this possible?
(defn create-db
  (try (db-do-commands
          db (create-table-ddl :temps
                               [[:timestamp :datetime :default :current_timestamp ]
                                [:location :text]
                                [:temp :real]]
       (catch Exception e
         (println (.getMessage e)))))
line 16 is the create-table-ddl line


create-db was already run literally > 24 hours earlier


Is there a stack trace after those 3 lines of error you showed? One thing it makes me immediately wonder is "if Clojure loaded that source file earlier, why was it trying to read the source file again later?" Do you have some explicit load or load-file call in your Clojure code that would cause that? Or a (require ...) with :reload-all as an arg?


Clojure is definitely a dynamic enough language that you can load source files long after the program begins running, but it is not the most common practice in Clojure programs to do so.


Here is the trace


 "Syntax error reading source at (tempplot/core.clj:21:1).\nEOF while reading, starting at line 16\n",                                                                              :clojure.main/triage
 {:clojure.error/phase :read-source,
  :clojure.error/line 21,
  :clojure.error/column 1,
  :clojure.error/source "core.clj",
  :clojure.error/path "tempplot/core.clj",
  :clojure.error/cause "EOF while reading, starting at line 16"},
  [{:type clojure.lang.Compiler$CompilerException,
    "Syntax error reading source at (tempplot/core.clj:21:1).",
    {:clojure.error/phase :read-source,
     :clojure.error/line 21,
     :clojure.error/column 1,
     :clojure.error/source "tempplot/core.clj"},
    :at [clojure.lang.Compiler load "" 7643]}
   {:type java.lang.RuntimeException,
    :message "EOF while reading, starting at line 16",
    :at [clojure.lang.Util runtimeException "" 221]}],
  :trace                                                                                                                                                                             [[clojure.lang.Util runtimeException "" 221]
   [clojure.lang.LispReader readDelimitedList "" 1405]
   [clojure.lang.LispReader$ListReader invoke "" 1243]
   [clojure.lang.LispReader read "" 285]
   [clojure.lang.LispReader readDelimitedList "" 1398]
   [clojure.lang.LispReader$ListReader invoke "" 1243]
   [clojure.lang.LispReader read "" 285]
   [clojure.lang.LispReader read "" 216]
   [clojure.lang.Compiler load "" 7631]
   [clojure.lang.RT loadResourceScript "" 381]
   [clojure.lang.RT loadResourceScript "" 372]
   [clojure.lang.RT load "" 459]
   [clojure.lang.RT load "" 424]
   [clojure.core$load$fn__6839 invoke "core.clj" 6126]
   [clojure.core$load invokeStatic "core.clj" 6125]
   [clojure.core$load doInvoke "core.clj" 6109]
   [clojure.lang.RestFn invoke "" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5908]
   [clojure.core$load_one invoke "core.clj" 5903]
   [clojure.core$load_lib$fn__6780 invoke "core.clj" 5948]
   [clojure.core$load_lib invokeStatic "core.clj" 5947]
   [clojure.core$load_lib doInvoke "core.clj" 5928]
   [clojure.lang.RestFn applyTo "" 142]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$load_libs invokeStatic "core.clj" 5985]
   [clojure.core$load_libs doInvoke "core.clj" 5969]
   [clojure.lang.RestFn applyTo "" 137]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.core$require invokeStatic "core.clj" 6007]
   [clojure.core$require doInvoke "core.clj" 6007]
   [clojure.lang.RestFn invoke "" 408]
   [user$eval140$fn__144 invoke "form-init798709166106965070.clj" 1]
   [user$eval140 invokeStatic "form-init798709166106965070.clj" 1]
   [user$eval140 invoke "form-init798709166106965070.clj" 1]
   [clojure.lang.Compiler eval "" 7177]
   [clojure.lang.Compiler eval "" 7167]
   [clojure.lang.Compiler load "" 7636]
   [clojure.lang.Compiler loadFile "" 7574]
   [clojure.main$load_script invokeStatic "main.clj" 475]
   [clojure.main$init_opt invokeStatic "main.clj" 477]
   [clojure.main$init_opt invoke "main.clj" 477]
   [clojure.main$initialize invokeStatic "main.clj" 508]
   [clojure.main$null_opt invokeStatic "main.clj" 542]
   [clojure.main$null_opt invoke "main.clj" 539]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "" 137]
   [clojure.lang.Var applyTo "" 705]
   [clojure.main main "" 40]],
  :cause "EOF while reading, starting at line 16",
  :phase :read-source}}


(ns tempplot.core
  (:require [dvlopt.linux.i2c :as i2c]
            [dvlopt.linux.i2c.smbus :as smbus]
            [ :as json]
            ;[oz.core :as oz]
            [ :refer :all]))

(def db
  {:classname "org.sqlite.JDBC"
   :subprotocol "sqlite"
   :subname "db/database.db"})

(defn create-db
  (try (db-do-commands
          db (create-table-ddl :temps
                               [[:timestamp :datetime :default :current_timestamp ]
                                [:location :text]
                                [:temp :real]]
       (catch Exception e
         (println (.getMessage e)))))

(defn minimum-legal-temp
  [datetime outside-temp]
  ; TODO: Add date awareness: Heat season is between Oct 1 and ??
  (if (and (>= (.getHour datetime) 6) (< (.getHour datetime) 22))
    (if (< outside-temp 12.78) ; Day time, if under 55°F, then keep 68°F
      outside-temp)            ; Otherwise there's no miniimum
    16.67))                    ; At night the minimum is always 62°F during heat season

  (minimum-legal-temp (java.time.LocalDateTime/of 2021 2 13 5 45) 10)
  (minimum-legal-temp (java.time.LocalDateTime/of 2021 2 13 15 45) 10)

(def reg-temp 0)
(def reg-config 1)
(def resolution 0.0078125)

(defn bytes->val
  (reduce (fn [acc v] (+ v (* acc 256))) b))

(bytes->val [8 201])

(def reading->C (partial * resolution))

(defn read-reg
  [bus reg]
  (i2c/transaction bus
        [{::i2c/slave-address 0x48
          ::i2c/write [reg]}
         {::i2c/slave-address 0x48
          ::i2c/read 2}]))

(defn line-plot
  {:data {:values (doall (query db ["select * from temps order by timestamp"]))}
   :encoding {:x {:field "timestamp" :type "nominal"}
              :y {:field "temp" :type "quantitative"}
              :color {:field "location" :type "nominal"}}
   :mark "line"})

(def api-host "")
(def api-key "xxx")
(def api-current-weather "")
(def manhattan-city-id 5125771)

(defn get-current-temperature
  (-> (format api-current-weather manhattan-city-id api-key)
      (get-in ["main" "temp"])))

(defn get-manhattan-temp [] (get-current-temperature manhattan-city-id))

(defn -main
  [& args]
  (println "Creating db")
  (create-db db)
  (println "Reading temps")
  (with-open [bus (i2c/bus "/dev/i2c-1")]
    (while true
    ;(dotimes [i (* 12 18)] ; for now
      (let [inside-temp (-> (read-reg bus reg-temp)
                  (get 1)
            outside-temp (get-manhattan-temp)
            now (java.time.LocalDateTime/now)
            min-temp (minimum-legal-temp now outside-temp)]
         (insert! db :temps {:location "inside" :temp inside-temp :timestamp now})
         (insert! db :temps {:location "outside" :temp outside-temp :timestamp now})
         (insert! db :temps {:location "minimum" :temp min-temp :timestamp now})
         (println (format "%s inside %.2fC outside %.2fC illegal? %s" now inside-temp outside-temp (< inside-temp min-temp))))
      (Thread/sleep (* 5 60 1000)) ; 5 minutes
  (spit "plot.edn" (line-plot db))

; {1 [8 201]}
; {1 [0 240]}


Do you know of any way that your program would try to load new Clojure source code long after it started?


Or was this exception perhaps caused because you had a live REPL session open with the running program, and you did something in the REPL that tried to load Clojure source code?


I'm only eyeballing it, but I see nothing about that source file that ends at line 21 🙂


Is there any chance that you were editing the source file after your program was already running?


no repl, no editing the file


it was on a raspberry pi I hadn’t touched


I just checked it this morning


and in fact the time stamp on the file was 13 hours before the error


Maybe the Pi itself reset for some reason? Would your program relaunch if the device rebooted?


how did you run clojure? via java directly, with clj, lein?


The file(form whatever.clj) name in a the stack trace means lein


so likely "lein run", I wonder if there's a hidden reloading plugin somewhere


you should look in the database to see what information was recorded in there, since it includes timestamps, my guess is you'll find less information than you expect, indicating that the error happened much earlier then you think


It does seem a lot more plausible that (a) the exception you showed actually occurred shortly after starting you program, perhaps because the file was not fully copied to the Raspberry pi where it was running somehow, but you did not notice it until much later, versus (b) the file was fully there when you started your program, got loaded once successfully then, your program for some reason tried loading it again 13 hours later (same running JVM process), and the file was somehow changed in a way that the modify time stamp did not get updated.


it’s worse than all of these. Sorry for setting you guys on a wild goose chase


I had opened the wrong stack trace facepalm


The problem is that I am doing a format "…%.2f" (api call) and when parsing the response json if the temperature happens to be exactly zero then the type is not a float


glad you found the actual problem!

Adrian Imanuel17:02:46

Hi, newbie question here, I'm using SQL server express, and some test database "AdventureWorks", but got an error java.sql.SQLException: No suitable driver found for jdbc:;DATABASENAME=AdventureWorks I've installed my jdbc via class path environment C:\Program Files\Java\jdk-15.0.2\mssql-jdbc-9.2.0.jre15.jar my code is

(ns clojuresql.core
  (:require [next.jdbc :as jdbc]
            [hugsql.core :as hugsql]
            [ :as adapter]
            [next.jdbc :as jdbc]
            [honeysql.core :as sql]
            [honeysql.helpers :refer :all :as helpers]))

(def db-sqlserver {:dbtype "sqlserver" :dbname "AdventureWorks"
                   :user "sa" :password "123456789"})

(def ds (jdbc/get-datasource db-sqlserver))

(jdbc/execute! ds
               ["show tables"])
where did i do wrong?


@adrianimanuel you don't "install" a jdbc driver, you add it as a maven dep to a project


(using any mainstream clojure option like lein or deps.edn at least)


you can check the output of (System/getProperty "java.class.path") to see if mssql-jdbc is mentioned anywhere

Adrian Imanuel17:02:10

@noisesmith oh, okay it's like this right com.h2database/h2 {:mvn/version "1.4.199"} , but for the SQLserver, from here [ "9.2.0.jre15"] am i right?


right - that's the normal way to do it - the general concept is that there's no global state of installed libs, but rather a config of which libs and versions you want, and a resolver that provides them to your process

👏 1
Adrian Imanuel17:02:17

ahh okay, noted... thanks so much!


this is weird at first! but now I find every other programming environment primitive. what do you mean I need to create a whole virtual OS / user environment just to use different lib versions in two projects?


a small upfront complexity to remove the avalanche of complexities that global installs create...


@adrianimanuel one more note - you have two sample lib specs there, the h2 example is in deps.edn format, the mssql one is in lein format - the two are easy to convert in your head but definitely make sure you have the right one

Adrian Imanuel17:02:35

yes, i read h2 in deps.edn format from But, noted, I'm using lein format to do that. I've got another error here, it's already connected but what should i do?

Execution error (SQLServerException) at (
The TCP/IP connection to the host, port 1433 has failed. Error: "Connect timed out. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.".

Adrian Imanuel17:02:40

i've also create inbound exception in the firewall for 1433 port


are you running things in WSL?


What's the rule on evaluation for vars that refer to vars? Might be a weird question, but I'm curious about why this works:

(def a inc)
(def b #'a)
(def c #'b)

;; #object[clojure.core$inc 0x2b39a1 "[email protected]"]
;; #exercises.core/a
;; #exercises.core/b

;; However, c still works as a function
(c 4)
;; 5
I kinda expected a function call to c would evaluate to the var b, and not the function object inc all the way down the chain. Does evaluation explicitly continuously unwrap vars until something that implements IFn , or instead is it that vars can function as functions that pass arguments down to whatever they're pointing at, thus c in the above example is just a bunch of nested function calls?


@eagonmeng when you call a var, it derefs and calls the thing it contains


refs do this too


it's not the evaluators job per se - var implements the IFn interface

user=> (supers clojure.lang.Var)
#{clojure.lang.Settable java.lang.Runnable clojure.lang.IFn java.util.concurrent.Callable clojure.lang.IDeref clojure.lang.IMeta clojure.lang.IRef clojure.lang.AReference java.lang.Object clojure.lang.ARef clojure.lang.IReference}


the evaluator takes the list (x) and since in most contexts () means call, it looks for the way to call the thing


so if x is a var, it finds that the var is an IFn (a first class thing clojure knows how to call), and invokes it


the object decides what "calling" means


in the var case, calling means calling the thing it contains, but really it's up to the object, it's not in clojure's compiler's control


using some OO primitives really helps here I think:

(cmd)user=> (def f (reify clojure.lang.IFn (invoke [this] "hi")))
(ins)user=> (f)


reify creates a thing that implements some interface, here it creates a thing clojure knows it can call - anything could go in that method


@noisesmith Thanks for the clarification! Makes sense, so it was the latter option I was thinking about. A lot more clean than baking in some weird unwrapping mechanism in evaluation, which was what I was confused about. Essentially vars ARE functions since they implement IFn , and they simply call the thing the thing they point at when treated as such, and thus sequentially referenced vars form a call chain until they hit an actual function or error out when they resolve to something that doesn't.