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])
Perfect, thanks!
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).
boom
yes good point, I was only thinking about the simple case of (when a b)
Also (and false x)
returns false
whereas (when false x)
returns nil
(though that often wouldn't matter)
Interestingly,
(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
{:clojure.main/message
"Syntax error reading source at (tempplot/core.clj:21:1).\nEOF while reading, starting at line 16\n",
:clojure.main/triage
But the file never changed, how in the world is this possible?
(defn create-db
[db]
(try (db-do-commands
db (create-table-ddl :temps
[[:timestamp :datetime :default :current_timestamp ]
[:location :text]
[:temp :real]]
:conditional?))
(catch Exception e
(println (.getMessage e)))))
line 16 is the create-table-ddl
linecreate-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
{:clojure.main/message
"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"},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message
"Syntax error reading source at (tempplot/core.clj:21:1).",
:data
{:clojure.error/phase :read-source,
:clojure.error/line 21,
:clojure.error/column 1,
:clojure.error/source "tempplot/core.clj"},
:at [clojure.lang.Compiler load "Compiler.java" 7643]}
{:type java.lang.RuntimeException,
:message "EOF while reading, starting at line 16",
:at [clojure.lang.Util runtimeException "Util.java" 221]}],
:trace [[clojure.lang.Util runtimeException "Util.java" 221]
[clojure.lang.LispReader readDelimitedList "LispReader.java" 1405]
[clojure.lang.LispReader$ListReader invoke "LispReader.java" 1243]
[clojure.lang.LispReader read "LispReader.java" 285]
[clojure.lang.LispReader readDelimitedList "LispReader.java" 1398]
[clojure.lang.LispReader$ListReader invoke "LispReader.java" 1243]
[clojure.lang.LispReader read "LispReader.java" 285]
[clojure.lang.LispReader read "LispReader.java" 216]
[clojure.lang.Compiler load "Compiler.java" 7631]
[clojure.lang.RT loadResourceScript "RT.java" 381]
[clojure.lang.RT loadResourceScript "RT.java" 372]
[clojure.lang.RT load "RT.java" 459]
[clojure.lang.RT load "RT.java" 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 "RestFn.java" 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 "RestFn.java" 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 "RestFn.java" 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 "RestFn.java" 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 "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7167]
[clojure.lang.Compiler load "Compiler.java" 7636]
[clojure.lang.Compiler loadFile "Compiler.java" 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 "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 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]
[clojure.data.json :as json]
;[oz.core :as oz]
[clojure.java.jdbc :refer :all]))
(def db
{:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname "db/database.db"})
(defn create-db
[db]
(try (db-do-commands
db (create-table-ddl :temps
[[:timestamp :datetime :default :current_timestamp ]
[:location :text]
[:temp :real]]
:conditional?))
(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
20
outside-temp) ; Otherwise there's no miniimum
16.67)) ; At night the minimum is always 62°F during heat season
(comment
(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
[b]
(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
[db]
{: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 "<http://api.openweathermap.org/data/2.5/forecast?id=524901&appid=>")
(def api-key "xxx")
(def api-current-weather "<https://api.openweathermap.org/data/2.5/weather?id=%d&appid=%s&mode=json&units=metric>")
(def manhattan-city-id 5125771)
(defn get-current-temperature
[city-id]
(-> (format api-current-weather manhattan-city-id api-key)
slurp
json/read-str
(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)
bytes->val
reading->C)
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
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:<sqlserver://127.0.0.1:1433>;DATABASENAME=AdventureWorks
I've installed my jdbc via com.microsoft.sqlserver.jdbc.SQLServerDriver
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]
[hugsql.adapter.next-jdbc :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
@noisesmith oh, okay it's like this right com.h2database/h2 {:mvn/version "1.4.199"}
, but for the SQLserver, from here
https://mvnrepository.com/artifact/com.microsoft.sqlserver/mssql-jdbc/9.2.0.jre15
[com.microsoft.sqlserver/mssql-jdbc "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
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
yes, i read h2 in deps.edn format from https://github.com/seancorfield/next-jdbc/blob/develop/doc/getting-started.md 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 com.microsoft.sqlserver.jdbc.SQLServerException/makeFromDriverError (SQLServerException.java:234).
The TCP/IP connection to the host 127.0.0.1, 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.".
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
followed this https://stackoverflow.com/questions/18841744/jdbc-connection-failed-error-tcp-ip-connection-to-host-failed and changed my ipall port to : 1433, but still got an error
i've also create inbound exception in the firewall for 1433 port
are you running things in WSL?
@dpsutton windows 10
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.
How to kill the current command in the REPL? I have something like (javadoc Object)
and I want to kill it is there a way? (it is "lein repl")
It seems that a workaround for that issue is to start the default browser first.
this should be a simple fix, as surely nobody uses javadoc in a critical path, it's easy to manage the stdio of a child with ProcessBuilder
There is a patch on the ticket I linked that led to improved behavior in my interactive testing. Alex Miller's last comment on it that I recall was that he'd like to think about it more and see if there is a better way. I do not know what the criteria for better is here.
ctrl + c twice maybe?
did not work
thats shortcut to kill in emacs
wait, why would javadoc
hang? it just shells out and returns immediately in my experience
nrepl, which lein uses, has a signal handler that kills the current top level execution on control-c
if javadoc hangs (maybe because your browser is set up weird?) that sounds like a bug in javadoc
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)
@#'a
;; #object[clojure.core$inc 0x2b39a1 "clojure.core$inc@2b39a1"]
@#'b
;; #exercises.core/a
@#'c
;; #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 java.io.Serializable 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")))
#'user/f
(ins)user=> (f)
"hi"
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.
If the person asking is using a Linux system with xdg-open installed, it might be related to this issue: https://clojure.atlassian.net/browse/CLJ-2493
oh wow - I never had xdg-open hang on me, I guess because I already had a browser running so it just opens a tab in that browser an returns immediately without the need to start a process
but yeah, good find, definitely a bug in javadoc