This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-09
Channels
- # announcements (3)
- # babashka (120)
- # beginners (87)
- # calva (7)
- # clj-kondo (35)
- # cljsrn (25)
- # clojure (94)
- # clojure-austin (4)
- # clojure-europe (53)
- # clojure-nl (2)
- # clojure-norway (6)
- # clojurescript (16)
- # conjure (8)
- # cursive (6)
- # data-oriented-programming (2)
- # data-science (19)
- # datahike (1)
- # datalevin (29)
- # datomic (13)
- # fulcro (50)
- # gratitude (1)
- # honeysql (9)
- # jackdaw (2)
- # kaocha (7)
- # leiningen (3)
- # malli (4)
- # off-topic (4)
- # polylith (3)
- # re-frame (5)
- # reagent (1)
- # releases (1)
- # reveal (4)
- # shadow-cljs (17)
- # tools-deps (10)
- # vim (17)
- # vscode (4)
- # xtdb (3)
I wrote the function get two sql statement and return. but It's return [] now. should I use atom saves the result or some easy way? like this remember the middle variable
(defn return-sql
[table-name remote-rows local-rows where]
(println "remote-count:" (count remote-rows) " local-count:" (count local-rows))
(let [execute-sqls []]
(if-not (empty? local-rows)
(conj execute-sqls
(-> {:delete-from table-name
:where where}
(hsql/format))))
(conj execute-sqls
(-> {:insert-into [table-name]
:values remote-rows}
(hsql/format {:pretty true})))))
or like this?
(defn return-sql
[table-name remote-rows local-rows where]
(println "remote-count:" (count remote-rows) " local-count:" (count local-rows))
(if-not (empty? local-rows)
[(-> {:delete-from table-name
:where where}
(hsql/format))
(-> {:insert-into [table-name]
:values remote-rows}
(hsql/format {:pretty true}))]
[(-> {:insert-into [table-name]
:values remote-rows}
(hsql/format {:pretty true}))]))
(return-sql :bz_project_item [{:id 100 :name "1#"} {:id 101 :name "2#"}],[{:id 100 :name "3#"} {:id 101 :name "4#"}] [:= :project_id 8892])
=> [["DELETE FROM bz_project_item WHERE project_id = ?" 8892]
["\nINSERT INTO bz_project_item\n(id, name) VALUES (?, ?), (?, ?)\n" 100 "1#" 101 "2#"]]
I use the jdbc/with-transcation
show errors:
(let [sqls (return-sql :bz_project_item [{:id 100 :name "1#"} {:id 101 :name "2#"}],[{:id 100 :name "3#"} {:id 101 :name "4#"}] [:= :project_id 8892])]
(jdbc/with-transaction [tx local-conn]
(for [sql sqls]
(jdbc/execute! tx sql)))
; Error printing return value (SQLException) at com.zaxxer.hikari.pool.ProxyConnection$ClosedConnection/lambda$getClosedConnection$0 (ProxyConnection.java:515).
; Connection is closed
something like:
(cond->> [insert-sql]
(empty? local-rows) (cons delete-sql))
for the second part, the problem is that for is lazy, so the transaction is closed before the for
is realized. You could replace by doseq
if you don't care about the return, or wrap the for
in doall
I use the next.jdbc/connection/->pool com.zaxxer.hikari.HikariDataSource
create pool with jdbc/with-logging
return object:
{:connectable #object[com.zaxxer.hikari.HikariDataSource 0x30f2d2d8 "HikariDataSource (HikariPool-1)"],
:sql-logger #function[xing.data.common/sql-logger],
:result-logger #function[xing.data.common/sql-result-logger]}
now I call .close
to close the connection, show error:
(.close conn)
; Execution error (IllegalArgumentException) at app.data-recover.core/eval11609 (REPL:6496).
; No matching field found: close for class next.jdbc.sql_logging.SQLLogging
I use (.close (:connectable remote-conn))
It's closed. About jdbc connection pool. Whether it should be closed manually after useQuick question, (tangentially Clojure-related):
I'm developing on windows, and want to tinker with the seesaw
library. When I try to download dependencies with Lein
, I get an error and the solution seems to be to add an http_proxy to environment variables. What I'm wondering is to what url should I set this?
That depends. Typically the need for such a proxy occurs at the workplace because of security concerns, so you would have to consult within your company. I assume that's your situation (more or less)?
if there are java developpers in the company you should be able to use the same url as the one defined in .m2/settings.xml (iirc, you could just set up this file, without touching lein)
@U03BYUDJLJF no this is my home computer!
Hmm alright. Can you share the output of your error? And how did you conclude that the proxy env vars seem to be a solution?
Exactly. It seems Stuart Sierra's repository supports it: https://stuartsierra.com/maven2 (source: https://stuartsierra.com/software/maven)
@U02F0C62TC1 got it, that said I'm just using lein deps
, how can I specify to use https vs http?
that's the first time i see a repository defined in a lib, can you try upgrading seesaw to 1.5.0 ?
otherwise you can do the http repo trick: add
(require 'cemerick.pomegranate.aether)
(cemerick.pomegranate.aether/register-wagon-factory!
"http"
#(org.apache.maven.wagon.providers.http.HttpWagon.))
I'm trying out clojure.test
and I'm a bit surprised by the output. For example:
; expected:
(= 0 1)
; actual:
(not (= 0 1))
I was curious if more people found this counter-intuitive and not as helpful as it could be by providing what the actual value is, instead of just prepending not
before the expected value.I've come across this library: https://github.com/pjstadig/humane-test-output So I know I'm not entirely alone. I was just wondering if people know the reason behind this design choice, and what are nice ways to change it (including perhaps this library). Most notably I would feel helped if I can get the Calva test runner to display neater results
That's not all it's doing. If you wrote something more complex, for example
(deftest thing
(let [a 1
b 2]
(is (= a b))))
you'd see that expected is (= a b)
and actual is (not (= 1 2))
so the first one is telling you what forms you ran and the second one tells you what values you got.See https://github.com/lambdaisland/kaocha and https://github.com/weavejester/eftest as other examples of test runners with that produce easy to read test results.
@U01AKQSDJUX, right, that's fair. I still feel a bit underwhelmed when comparing to the example output in the library mentioned above (or something like pytest in Python).
@UE21H2HHD I intend to look into different test runners for sure! Currently I'm looking for something to run against a running REPL (ideally from within Calva) during development
@U03BYUDJLJF be sure to check out #calva if you get stuck, you'll find a super helpful group over there.
Thanks all!
I use cider (and I'm under the impression that calva uses the same nrepl + middleware tooling that cider uses, though I'm not a vs code user so prepared to be corrected on this 😉 ) but given a more complex test case such as
(deftest thing
(let [a {:a 1 :b 2 :c 3}
b {:a 1 :b 2 :c 1}]
(is (= a b))))
by default I now get
expected: {:a 1, :b 2, :c 3}
actual: {:a 1, :b 2, :c 1}
diff: - {:c 3}
+ {:c 1}
which I would expect calva to do to. There are a bunch of alternative test systems available that a lot of people seem to like, but I've never felt it was worth the effort to switch.That looks nice! I'm also pretty confident there's some shared tooling between Calva and Cider, but judging from my output using your test example there's some differences as well:
expected: {:a 1, :b 2, :c 3}
actual: {:a 1, :b 2, :c 1}
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
{:test 1, :pass 0, :fail 1, :error 0, :type :summary}
Although, to my surprise, it does show the actual value.
Anyways, Calva doesn't support customizing this, so I'm going to accept if for now 🙂. I am also trying out Doom Emacs with Cider. Lots of positives so far, but it takes some time to get used to everything.How do i kill a process programatically that was started with
clojure.java.shell
?
i have a code that (sh "ffmpeg"...)
saves a stream locally but i want to chunk it in bits.
doesn't look like it, well except (sh "kill" ...)
😅
however you could write your own function that handle it, starting from (source sh)
(with-open [stdout (.getInputStream proc)
stderr (.getErrorStream proc)]
(future
(try
(let [out (future (stream-to-enc stdout out-enc))
err (future (stream-to-string stderr))
exit-code (.waitFor proc)]
{:exit exit-code :out @out :err @err})
(catch InterruptedException e (.destroy proc))))
(parentheses are most likely wrong)
you'd now get a future, which you can future-cancel
Are you sure killing the process is the right way of doing it though ? ffmpeg may have an option for chunkingHey! I figured out that ffmpeg has duration so i am gonna use that 🙂 Thanks for this
You could also take a look at https://github.com/babashka/process
Is there some kind of control structure in clojure I could use for this kind of method in java which goes through a few expensive-to-compute results and conditionally returns the first that satisfies a condition?
public int foo() {
int i = expensiveComputation();
if (someCondition(i)) {
return i;
}
i = expensiveOtherComputation();
if (someOtherCondition(i)) {
return i;
}
i = expensiveThirdComputation();
if (thirdCondition(i)) {
return i;
}
//...
}
I would naturally lean on cond
but that doesn't let you reuse things in the condition and the return value so you'd be doing double work
(defn foo []
(cond
(some-condition (expensive-computation)) (expensive-computation)
(some-condition2 (expensive-computation2)) (expensive-computation2)
(some-condition3 (expensive-computation3)) (expensive-computation3)
;;...
))
perhaps reducing over a vector of compute
, condition
and result
functions is easiest
(defn foo []
(reduce (fn [_ [com con res]]
(let [value (com)]
(if (con value) (reduced (result value)) nil)))
nil
[[compute1 condition1 result1] [compute2 condition2 result2] [compute3 condition3 result3]]))
you could have someCondition
return i
and then make it or
(or (someCondition (expensiveComputation))
(someOtherCondition (otherComputation)))
etcperhaps use laziness? map i
through a collection of expensive functions fs
, then do something similar to run them through conditions, take the first true.
oh ya afleck this works nicely
(or
(let [i (some-computation)] (when (some-condition i) i))
(let [i (other-computation)] (when (other-condition i) i)))
@U1Z392WMQ unfortunately then you get into territory of having to make sure you aren't using chunked sequences which will go through a whole 32-chunk of your expensive or io-laden branches
you could also use a delay
(let [x (delay (prn 'expensive 'calculation) (+ 1 2))
y (delay (prn 'not 'run) (+ 3 4))]
(cond (= 3 @x) @x
:else @y))
This will run the computation only once when it is defrefed and would allow you to chain the computations if you need toyou may want to look into manifold https://github.com/clj-commons/manifold if you run into async stuff like this a lot. it has control structures for this type of logic, mainly let-flow https://cljdoc.org/d/manifold/manifold/0.2.4/api/manifold.deferred#let-flow
How about
(defn compute-and-check
[[compute & computes] [condition & conditions] input]
(when (and (function? compute)
(function? condition))
(let [result (compute input)]
(if (condition result)
[result [compute condition input]]
#(compute-and-check computes conditions input)))))
(trampoline compute-and-check computations conditions input)
My 2cents:
(def computations-with-checks
[[computation1 predicate1]
[computation2 predicate2]
; etc.
])
(defn computes-ok [[computation ok?]]
(let [result (computation)]
(when (ok? result) result)))
(some computes-ok computations-with-checks)
Follow-on to last night's issue:
Trying to use Seesaw to play with UIs, when I run build
in lein
, get an error that x11 Display is not set. Been doing a bunch of reading, and seems like it is an issue with "headless" versions of java that use java.awt library. That said, I can't figure out how to solve / get around this, resetting display in the terminal doesn't work (e.g. export DISPLAY=:0
, etc.); I've tried uninstalling and resinstalling Java itself, and I'm not sure how to set a headless mode inside of a Clojure app (or if that would even work). Any thoughts?
I believe the headless version applies to the jvm itself. How did you install java/the jvm?
A workaround is to run it with something like xvfb, but obviously it won't pop up any windows.
Are you trying to run your GUI over ssh?
What is your dev setup like?
if you have a headless jvm build, then the classes / code needed to do guis are missing, and you need to install a non-headless jvm
on linux you may also be on wayland and x11 (in theory wayland has some kind of fallback story, but I dunno)
Believe I used apt via a linux distro (on WSL, i.e. Linux for windows). Can send my env and java build in a bit
Incredibly strangely, if I just import java.swing and create a UI using that (and not Seesaw), it works...
you may need to make sure any gui apps work in wsl before looking at java gui apps (https://docs.microsoft.com/en-us/windows/wsl/tutorials/gui-apps)
Thanks @U0LAJQLQ1 and @U0NCTKEV8
your "map"ing over the list [ 1 1 ...] and applying the function #(+ % 1) to each value to get the output [2 2 ...]. It's like a for loop It's like doing 1 + 1 = 2 1 + 1 = 2
try (map inc [0 1]) for similar results
i just saw that everyone replied under "HI". lol