This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-03-16
Channels
- # babashka (40)
- # beginners (71)
- # calva (65)
- # cider (8)
- # clerk (10)
- # clj-kondo (14)
- # clojure (58)
- # clojure-austin (5)
- # clojure-czech (1)
- # clojure-europe (24)
- # clojure-nl (1)
- # clojure-uk (6)
- # core-matrix (1)
- # cursive (8)
- # datomic (20)
- # docker (38)
- # emacs (2)
- # events (1)
- # fulcro (4)
- # funcool (3)
- # hyperfiddle (77)
- # introduce-yourself (1)
- # lsp (31)
- # malli (32)
- # off-topic (11)
- # pathom (3)
- # re-frame (11)
- # reagent (15)
- # releases (2)
- # shadow-cljs (38)
- # sql (3)
- # tools-deps (35)
How do I pretty-print an exception the same way Clojure prints exceptions by default? I found https://clojuredocs.org/clojure.stacktrace, I believe it's what does it, but I can't load it:
(require '(clojure.stacktrace))
nil
clojure.stacktrace/print-throwable
Syntax error (ClassNotFoundException) compiling at (REPL:0:0).
Context: I caught an exception, I want to print a custom message first and then pretty-print the exception.(require 'clojure.stacktrace)
-- not sure why you have parens around it?
build=> (require 'clojure.stacktrace)
nil
build=> clojure.stacktrace/print-throwable
#object[clojure.stacktrace$print_throwable 0xebfa509 "[email protected]"]
build=> (doc clojure.stacktrace/print-throwable)
-------------------------
clojure.stacktrace/print-throwable
([tr])
Prints the class and message of a Throwable. Prints the ex-data map
if present.
nil
I see. I nearly always use it with ns
, so I got confused.
If I require
with parens like your example, I get that same exception (but that's not legal require
syntax, right?)
I was confused that it returned nil
.
OK, that explains 🙂 Thanks @U04V70XH6
You can (require '[clojure.stacktrace])
as a vector...
(~/clojure)-(!2002)-> clj
Clojure 1.11.1
user=> (require '[clojure.stacktrace])
nil
user=> clojure.stacktrace/print-throwable
#object[clojure.stacktrace$print_throwable 0x4acf72b6 "[email protected]"]
user=>
Wed Mar 15 17:23:44
(~/clojure)-(!2003)-> clj
Clojure 1.11.1
user=> (require '(clojure.stacktrace))
nil
user=> clojure.stacktrace/print-throwable
Syntax error (ClassNotFoundException) compiling at (REPL:0:0).
clojure.stacktrace
user=>
Yeah that's it, I confused the vector syntax.
what am I missing about wanting existing instances to have updated behavior after a deftype/defrecord ?
maybe I should me using defmulti/defmethod instead of relying on deftype and protocols? or not?
I want to evolve the implementation of my protocol without rebuilding my instances which contain state like network connections
to implement a protocol ensuring the abstractions are used, and to have runtime polymorphism
What sort of thing are you abstracting over? Data or state and operations? Even with protocols you have several options, including extend-protocol and extension via metadata It's rare to need new concrete types in Clojure If it's just data, multimethods may be better Also see https://github.com/cemerick/clojure-type-selection-flowchart
A component that I want to be able to swap for another implementation or a mocking implementation. It started as just immutable data but is evolving to state, by keeping maps to connect implementation behaviors to abstractions inside the app's domain. I had started with deftype and moved now to defrecord, but yeah I'm still a bit lost
I've seen it from a distance, haven't dug in at all. With defmulti ? Right maybe that's it. Though then I wonder how I'd "ensure" that all implementations implement the full thing
sorry I've been too abstract -- to make this more concrete, imagine a communication abstraction over IRC and Matrix
but regardless, imagining whatever use-case that for sure would require deftype for example, I wonder how people keep the REPL quick redefinition dev approach given the instances are not updated
In that case multimethods are usually used You can also take apart building messages and sending them, then have a single client protocol with a single method (send) and a multimethod for building messages of different types
Make protocols for what can be locked down early, you identified something interesting
Hmmmm okay. Makes sense, as I don't know what I want the interface to be like yet. I wonder if it's not a common practice also to have deftypes
s (as an example) that end up just proxying calls to isolated functions, so implementations remain uncoupled. I guess in the end there's no difference, except the proxying would make redefining easier, so probably not. Thanks for reaching back.
Deftypes are rare, we usually Just Use Functions (TM) until we have a good reason not to
which function process data like this in clojure
(def f [fn1 fn2 fn3 ... ])
(apply-fun f data) like this (-> data fn1 fn2 fn3)
id pretty much use what you said ->
. dont see much of a value in having something more
look at comp
((comp fn3 fn2 fn1) data)
reduce is handy if the list of functions should be treated as data..
(def f [vector list])
(def data 42)
(reduce
(fn [a f] (f a))
data
f) ;; => ([42])
@U0HG4EHMH Thanks. That's what I want
comp
can be used with a list of functions:
((apply comp (reverse f)) data) ;; => ([42])
amazing @U04V4KLKC This code is even less:+1:
Hi, I have this function which converts euler angles (yaw, pitch and roll - if we refer to an aircraft) to a quaternion (which is a 3d rotation representation form). The function performs some calculations and then passes the value to a function from another namespace to construct the quaternion. It works ok. Is this a correct way to write such functions in Clojure (purely mathematical)? Is there a more idiomatic way?
(defn euler->quat
"Yaw, Pitch, Roll order (ZYX) - angles in degrees.
Output in x y z w quaternion."
[yaw pitch roll]
(let [y (degrees->rad yaw)
p (degrees->rad pitch)
r (degrees->rad roll)
cos-y (Math/cos (/ y 2))
cos-p (Math/cos (/ p 2))
cos-r (Math/cos (/ r 2))
sin-y (Math/sin (/ y 2))
sin-p (Math/sin (/ p 2))
sin-r (Math/sin (/ r 2))
w (+ (* cos-r cos-p cos-y) (* sin-r sin-p sin-y))
x (- (* sin-r cos-p cos-y) (* cos-r sin-p sin-y))
y (+ (* cos-r sin-p cos-y) (* sin-r cos-p sin-y))
z (- (* cos-r cos-p sin-y) (* sin-r sin-p cos-y))]
(q/quaternion x y z w)))
(defn euler->quat
"Yaw, Pitch, Roll order (ZYX) - angles in degrees.
Output in x y z w quaternion."
[& args]
(let [ypr (mapv #(/ (m/to-radians %) 2) args)
[cos-y cos-p cos-r] (mapv m/cos ypr)
[sin-y sin-p sin-r] (mapv m/sin ypr)
...]))
m
is clojure.math
. But I would check the speed of both, if you care about performance.I actually like your code @U04R06XSJV7. It looks very clear and reads nicely.
making the let bindings on top more compact like @U01RL1YV4P7 does, makes sense to me as well. It's a bit more compact and more nicely grouped. But your initial code looks perfectly fine to me.
My 2cents about performance: destructuring kills it, type hinting helps a lot. You may turn on (set! *unchecked-math*** :warn-on-boxed)
to verify if you work on primitives (certainly not). Regarding the code structure - for me it's really good and clean.
(defn degrees->rad
^double [^double degrees]
(/ (* Math/PI degrees) 180.0))
(defn euler->quat
"Yaw, Pitch, Roll order (ZYX) - angles in degrees.
Output in x y z w quaternion."
[^double yaw ^double pitch ^double roll]
(let [y (/ (degrees->rad yaw) 2.0)
p (/ (degrees->rad pitch) 2.0)
r (/ (degrees->rad roll) 2.0)
cos-y (Math/cos y)
cos-p (Math/cos p)
cos-r (Math/cos r)
sin-y (Math/sin y)
sin-p (Math/sin p)
sin-r (Math/sin r)
w (+ (* cos-r cos-p cos-y) (* sin-r sin-p sin-y))
x (- (* sin-r cos-p cos-y) (* cos-r sin-p sin-y))
y (+ (* cos-r sin-p cos-y) (* sin-r cos-p sin-y))
z (- (* cos-r cos-p sin-y) (* sin-r sin-p cos-y))]
(q/quaternion x y z w)))
Here’s my quaternion code in Clojure… https://github.com/mentat-collective/emmy/blob/main/src/emmy/quaternion.cljc
Emmy takes the approach of writing code using multimethods, but then compiling down to a fast representation for end uses
https://www.johndcook.com/blog/2021/06/16/faster-quaternion-rotations good reading too!
Thanks, your opinions are invaluable to me!
if you want speed, the data science clojure group (on slack and more on zulip) can probably help, as they are familiar with libs that use the GPU for math (eg: Neanderthal)
Will check that out, thank you!
Hi everyone, I'm playing around with a mongodb collection (using congomongo) where one of the document's keys is @context
. The documents are returned as a list of maps
(-> documents first keys)
;; => (:description :_id :validThrough :employmentType :datePosted #viewer-eval (keyword "@context") :jobLocation :hiringOrganization :title :skills :experienceRequirements :identifier #viewer-eval (keyword "@type"))
My question: is how do reference @context
?It's probably convenient to def
a few aliases:
(def at-context (keyword "@context"))
(def at-type (keyword "@type"))
... (get doc at-context) ... (get doc at-type) ...
Or you could just do that "in-place": ((keyword "@context") doc)
;=> (:@context doc)
;=> value of @context
field.
It worked! Thanks! 😀
Hi All,
(defn get-all-benchmarks [context cost-id area-code filters use-cache?]
(let [filters-with-identifiers (assoc filters "client-id" (get-in context [:context :client-id])
"cost-id" cost-id
"area-code" area-code)
services [#(try (get-country-benchmarks context
(-> (assoc filters-with-identifiers "srv" "country-benchmarks")
to-map-key
object-to-str) cost-id area-code filters
use-cache?)
(catch Exception e
(throw (ex-info (.getMessage e)
{:cause :bad-data}))))
#(try (get-site-benchmarks context
(-> (assoc filters-with-identifiers "srv" "site-benchmarks")
to-map-key
object-to-str) cost-id area-code filters
use-cache?)
(catch Exception e
(throw (ex-info (.getMessage e)
{:cause :bad-data}))))
#(try (get-study-benchmarks context
(-> (assoc filters-with-identifiers "srv" "study-benchmarks")
to-map-key
object-to-str) cost-id area-code filters
use-cache?)(catch Exception e
(throw (ex-info (.getMessage e)
{:cause :internal-server-error}))))]]
(->> services
(mapv (fn [service]
(async/thread
(service))))
(async/merge)
(async/reduce conj [])
(async/<!!)))
)
the code above has 3 different service (in separate threads) even though any one of them fails with exception that final result is still being constructed and exception doesn't bubble up, since it's in different thread. How can I make sure that exception is thrown by breaking the flow.....One option is for those services to return the (ex-info ..)
result instead of throwing it, then somewhere in your processing of the results, see if you got (instance? Exception result)
and if so, (throw result)
(Exceptions as "just" values so you can pass them around)
But since you're doing everything async up until the <!!
, you probably won't be able to throw overall until after you have that vector of results.
thanks for your response Sean
Is there a way to do what`clojure.set/intersection` , preferably without having to require clojure.set and converting what I have (in lists) into sets? Like it's not a big deal, but if there'd be a short(er) version that works with lists (or vectors), would be cool.
Well, if you had ONE set and one vector, you could use (filter some-set the-vector)
because Clojure sets work as a lookup function. (Which vectors do not; it would encourage linear searching.) Given two vectors, you had better convert one (maybe the smaller one) to a set in order to get fast lookups. If your vectors are so short that you don't care about fast lookups, then conversion to a set will also be a non-concern. So: (filter (set vector-a) vector-b)
... in short, you don't need clojure.set for intersection.
Whaaaat? That's wild!
Exactly what I was looking for. Cheers @U0HG4EHMH!
Clojure doesn't stop to surprise me 🙂
Hahaha yeah. I'm loving it! But my head spins like crazy at times that's for sure.
Had to do some JS (which I normally like), but after Clojure I was like what? Syntax? F*ck that!
(let [coll [[:a :b] [:b :c] [:d :b]]]
(reduce (comp set filter)
(-> coll first set)
(rest coll)))
I'm on CLJS for all that now 🙂 Starting a new project, it has a tight deadline, my CLJ skills aren't great (but I get by), I was considering it and was like I want to work with CLJ no matter what, so here I am! Moonlighting to learn, to fill in gaps in my skills, but really loving it.
I find that requiring clojure.set doesn't come up too often for me, and I use the set functions a lot, just not in most namespaces. I think set/intersection is more informative than the filter example, which is more like a clojure idiom.
Hahaha totally, but I appreciate the short version.