This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-04-09
Channels
- # announcements (26)
- # asami (1)
- # babashka (7)
- # beginners (51)
- # calva (1)
- # cider (18)
- # clj-kondo (6)
- # clj-together (1)
- # cljsrn (4)
- # clojure (78)
- # clojure-australia (3)
- # clojure-europe (25)
- # clojure-losangeles (1)
- # clojure-nl (2)
- # clojure-serbia (4)
- # clojure-spec (23)
- # clojure-uk (19)
- # clojurescript (23)
- # community-development (13)
- # deps-new (1)
- # emacs (24)
- # figwheel-main (5)
- # fulcro (61)
- # graalvm (1)
- # honeysql (11)
- # jobs (1)
- # lsp (7)
- # malli (4)
- # meander (6)
- # membrane (3)
- # off-topic (10)
- # polylith (13)
- # quil (7)
- # re-frame (54)
- # reagent (18)
- # remote-jobs (2)
- # shadow-cljs (81)
- # sql (16)
- # tools-deps (12)
- # xtdb (10)
is there a good place to talk about libraries like sente? i have some architecture questions. i saw #ring but that doesn't seem to cover web sockets
@nbtheduke I don’t see any more specific channels so you could ask here. At least once folks see the question, they’ll know whether there’s a better channel for it…
(I haven’t used Sente for years but I can take a stab at it maybe)
i'm wondering about how to handle authorization in sente handlers. As an example, using Compojure for http requests lets me say: (wrap-routes admin-routes auth/wrap-authorization-required)
, and then in wrap-authorization-required
, i can say (if (:admin user) (handler req) (response 401 ...))
I can’t remember whether Sente exposes header information but I seem to recall we tackled this somehow, back in the day. I think we passed some sort of auth token back to the server?
@nbtheduke The “official” Sente example app has a stub for login/auth https://github.com/ptaoussanis/sente/blob/master/example-project/src/example/server.clj
Oh, maybe I've completely misunderstood then. So the authentication happens when the websocket connection is made, not at each message sent?
If you have a clustered setup and you lose connectivity to one server and failover to another, you have to reestablish the auth'd status on the new server. Something to thing about.
I'm dipping my toes in the 'next-jdbc' waters, and ran into a small issue. It's probably a gap in my knowledge of streaming, but here goes....
I have a query using 'plan' that then can be reduced 'into []' with no issue.. it's a huge result set, which is what I expect.
But when I try to reduce that into something streamable, I'm getting an empty result..
So...
(ring-io/piped-input-stream
(fn [ostream]
(let [^java.io.Writer w ( ostream {})]
(get-big-data-streaming w))
(.close ostream)))
This is in the handler ☝️:skin-tone-2:
And the function of interest:
(reduce (fn [^java.io.Writer w record]
(let [m (datafiable-row record *db* {})]
(.write w m)
))
writer
(jdbc/plan *db* sv))
We can safely assume that sv
is a sqlvec that works and generates a large dataset outside of this streaming code
So the 'w' passed in is the Writer and locally is named writer
Hitting the endpoint takes about 4 seconds, the same as the non-streaming version, but returns no data.
@jmckitrick Not exactly the answer you’re looking for, but for anything next.jdbc
-related you can also ask in #sql
Hi. I am trying to implement a protocol for a type I am defining as part of clojure.core.matrix
mp/PFunctionalOperations
(element-map!
([m f]
(.modifyAll (.-array1d m) (UnaryFn. f)))
([m f a]
(.modifyMatching (.-array1d m) (BinaryFn. f) (.-array1d a)))
([m f a more]
(.modifyMatching (.-array1d m) (BinaryFn. f) (.-array1d a))
(doseq [b more] (.modifyMatching (.-array1d m) (BinaryFn. f) (.-array1d b)))))
The class UnaryFn
implements a functional Java interface allowing me to pass in clojure.lang.IFn
to method .modifyAll
which expects a Java lambda. When I test this functionality on its own it works perfectly, but when I include it in the protocol implementation it fails (see below). Can anyone help me understand why?
; --------------------------------------------------------------------------------
; eval (current-form): (def m (create-vector [1 2 3]))
#'ojalgo-clj.core/m
; --------------------------------------------------------------------------------
; eval (selection): m
(1.0 2.0 3.0)
; --------------------------------------------------------------------------------
; eval (current-form): (.modifyAll (.-array1d m) (UnaryFn. inc))
nil
; --------------------------------------------------------------------------------
; eval (selection): m
(2.0 3.0 4.0)
; --------------------------------------------------------------------------------
; eval (current-form): (deftype Vector [^Array1D array1d] Object (toSt...
; (err) Syntax error macroexpanding clojure.core/let at (C:\Git\ojalgo-clj\src\clojure\ojalgo_clj\core.clj:18:1).
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: simple-symbol? at: [:bindings :form :local-symbol] spec: :clojure.core.specs.alpha/local-name
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: vector? at: [:bindings :form :seq-destructure] spec: :clojure.core.specs.alpha/seq-binding-form
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: map? at: [:bindings :form :map-destructure] spec: :clojure.core.specs.alpha/map-bindings
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: map? at: [:bindings :form :map-destructure] spec: :clojure.core.specs.alpha/map-special-binding
That looks like a syntax error related to something else than the matrix or UnaryFn
stuff per se
It seems like you accidentally put (.modifyAll (.-array1d m) (UnaryFn. f))
into a binding position but I don't see anything like that in your initial snippet
Thanks for the run!
tip. So if I take out the arity overloading like so
(element-map!
[m f]
(.modifyAll (.-array1d m) (UnaryFn. f)))
It compiles. So it has to do with the binding introduced by the multiple arities?If I have
(element-map!
([m f]
(.modifyAll (.-array1d m) (UnaryFn. f))))
It macro expands to
(element-map!
[p__18280 p__18281]
(clojure.core/let
[[m f] p__18280 (.modifyAll (.-array1d m) (UnaryFn. f)) p__18281]))
Which in turn leads to
; eval (current-form): (deftype Vector [^Array1D array1d] Object (toSt...
; (err) Syntax error macroexpanding clojure.core/let at (C:\Git\ojalgo-clj\src\clojure\ojalgo_clj\core.clj:19:2).
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: simple-symbol? at: [:bindings :form :local-symbol] spec: :clojure.core.specs.alpha/local-name
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: vector? at: [:bindings :form :seq-destructure] spec: :clojure.core.specs.alpha/seq-binding-form
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: map? at: [:bindings :form :map-destructure] spec: :clojure.core.specs.alpha/map-bindings
; (err) (.modifyAll (.-array1d m) (UnaryFn. f)) - failed: map? at: [:bindings :form :map-destructure] spec: :clojure.core.specs.alpha/map-special-binding
when evaluated.Now I remember, you have to do it like this https://github.com/nilern/monnit/blob/main/src/monnit/pair.cljc#L11-L26
Aha! Thanks, I was looking at an extend-protocol
example which works with the parens. Thank you very much for the help.
Hey team, I want to create a handy help to time and log other function calls.
(defmacro with-logging [k body]
`(let [start-ms# (System/currentTimeMillis)
res# ~body
end-ms# (System/currentTimeMillis)]
(log/infof {:k ~k :ms (- end-ms# start-ms#)})
res#))
So, to use this, I could do something like :
(defn get-foo [id] (with-logging :get-foo (db/get ["select * from foos where id = ?" id])))
One pesky thing though, is that I need to repeat myself here: :get-foo
is the same as the fn def name
Is there a way you would change this, so this is not necessary? Am thinking of creating a macro, but what I have in mind seems a bit too involved&env
does not give the fn name as a local so you would need a defn
-like macro
You could use (.. Thread currentThread getStackTrace)
but that might trigger deoptimization, not good for profiling
@stopachka one useful strategy is to capture the form/expression itself so you don't have to synthesize a name
(defmacro timing [expr]
`(let [s# (System/currentTimeMillis)
ret# ~expr
time# (- (System/currentTimeMillis) s#)]
{:ret ret#
:time time#
:expr '~expr}))
> (source time)
(defmacro time
"Evaluates expr and prints the time it took. Returns the value of
expr."
{:added "1.0"}
[expr]
`(let [start# (. System (nanoTime))
ret# ~expr]
(prn (str "Elapsed time: " (/ (double (- (. System (nanoTime)) start#)) 1000000.0) " msecs"))
ret#))
(defn t [f k] (let [n (System/nanoTime)] (k (f) (/ (- (System/nanoTime) n) 1e6))))
If you wanted to implement a user or content driven recommendation system in a JVM/Clojure/Postgres project what libraries would you look at? Cortex?
I would ask in Zulip in https://clojurians.zulipchat.com/#narrow/stream/151924-data-science
Hi folks! I believe I have seen the recommendation to use when
instead of if
when I only care about the truthy branch, i.e. (when cond someting)
instead of (if cond someting)
. I wanted to refer to it but could not find it. Am I just making it up?
I remember a recentish discussion on this as well. I found https://www.reddit.com/r/Clojure/comments/3x44qx/style_question_and_if_when/ but I think it was brought up more recently though I can't remember where
you aren't making it up: https://guide.clojure.style/#when-instead-of-single-branch-if https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#missing-else-branch
Thanks a lot! I was looking into the guide but just could not see it 🙂
No, actually the guide says
> Use when
instead of (if … (do …))
.
I just skipped that because here I did not have a do
🙂
FWIW, Phil Hagelberg (technomancy) has pretty strong opinions about this: he thinks when
should only be used for side-effecting things and that a single-branch if
for pure code is just fine. I think he still holds that anyway. Certainly, there was a very pointed commit to Leiningen some years back that replaced when
with if
in a lot of places.
https://github.com/technomancy/leiningen/commit/f362d596f5879ad6cb6b9932124932388572959a
(I don’t agree with that but it sticks in my mind as a specific preference from a well-known Clojurian)
Thank you for sharing that!
@U04V70XH6 The irony is I believe the Sonian team (where Phil used to work) would reject any PR that had a single branch if
. @U0NCTKEV8 do you remember if that was the case?
is there any extra overhead incurred by having the implicit do
?
or does that get optimized away when it’s clear there is only one form?
that makes sense. I think
I’m trying to figure out a good way to create a lazy list of vectors in this shape:
[[0 0 0]
[1 0 0]
[1 1 0]
[1 1 1]
[2 1 1]
[2 2 1]
[2 2 2]]
(basically increments on an item by item basis) — i have something roughly working but it’s not particularly nice so curious what other ideas people may have(take 10 (reductions (fn [a b] (update a b inc)) [0 0 0] (cycle (range 3))))
that is very cool 😅
also, I always forget about cycle
but probably I wouldn’t have come up with this approach either way 😄
thanks @UQY3M3F6D!
Freaking awesome. It’d have been taking me years to come up with such solution @UQY3M3F6D
@U050TNB9F Here's a cute code-golf-y solution:
(->> (range) (map #(quot % 3)) (partition 3 1) (map reverse) (take 10))
That said, while this is slightly more succinct, I much prefer @UQY3M3F6D’s version as it conveys the semantics of the intended operation much better.