what's the best way to check to see if an object is an error?
(instance? Exception v*)
?
maybe (instance? Throwable v*)
I think any other method would just wrap that instance check
You should not (catch Throwable ...
so (instance? Throwable ...
might not be a good idea
https://docs.oracle.com/javase/8/docs/api/java/lang/Error.html
OTOH Error
s definitely are errors
And then there are non-`Throwable` error values like https://cljdoc.org/d/com.deepbeginnings/monnit/0.1.2/api/monnit.result#Err (shameless plug) If you need to support those then a protocol or multimethod would be in order
:thinking_face:
user> (instance? Error (ex-info "" {}))
false
user> (instance? Exception (ex-info "" {}))
true
user> (instance? Throwable (ex-info "" {}))
true
ExceptionInfo extends Exception extends Throwable
Error extends Throwable
sounds like I should check for Throwable then
It depends. I guess you are doing something like (let [v (<!! chan)] (if (error? v) (throw v) v))
?
Is there a way to bind dynamic variables in macro expansion? Something like
(def ^:dynamic *dyn*)
(defmacro foo
[]
(binding [*dyn* 1]
`(bar)))
(defmacro bar
[]
(let [v *dyn*]
`(println ~v)))
I think Throwable
would be right in that case but in practice something funky is going on if there is an Error
as a value
yes exactly 😄
I don't think so. The compiler calls macros in a kind of prewalk so by the time bar
expands foo
has already returned.
Or you could call macroexpand
yourself in foo
but that is going into Racket-level macro-fu
https://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf
But you can give bar
extra parameters that end-users might never pass but foo
does. Or maybe bar
is not even public. As a Schemer that is how I would approach this e.g. http://synthcode.com/scheme/match.scm
;; This is the guts of the pattern matcher. We are passed a lot of
;; information in the form:
;;
;; (match-two var pattern getter setter success-k fail-k (ids ...))
;;
;; usually abbreviated
;;
;; (match-two v p g+s sk fk i)
;;
;; where VAR is the symbol name of the current variable we are
;; matching, PATTERN is the current pattern, getter and setter are the
;; corresponding accessors (e.g. CAR and SET-CAR! of the pair holding
;; VAR), SUCCESS-K is the success continuation, FAIL-K is the failure
;; continuation (which is just a thunk call and is thus safe to expand
;; multiple times) and IDS are the list of identifiers bound in the
;; pattern so far.
(define-syntax match-two
But of course fancy macro tricks are not idiomatic in Clojure
So my options are either writing my own code walker or an anaphoric macro
not thrilled about either
I ended up solving this a different way. My use case is I have two core.async channels, one for errors and one for success. I ended up doing this:
(a/go
(let [[res c] (a/alts! [error-chan complete-chan])]
(if (= c error-chan)
(reject res)
(resolve res))))
so instead of asking whether it's instance?
of something, I just check to see if it came from the error-chan
elsewhere I have a try
/ catch
in a go-loop
that chooses whether to put on the error-chan
or complete-chan
yeah it's a bummer
btw, you can use identical?
when checking the returned channel from alts
It's really apropo of nothing, just slightly faster
👍:skin-tone-2:
Suppose I have the following map: {:user/goo 1 :user/bar 8 :user/foobar 9 :content/foobarbaz 10}
. Is there a way to get the contents of just the namespace :user/
from this map?
Probably the easiest would be to reduce-kv
over it and check (if (= "user" (namespace k)) (assoc m k v) m)
as the 3-arity reducing function.
There's filter-keys
from medley if you want to bring in a util library https://weavejester.github.io/medley/medley.core.html#var-filter-keys (or you could just name @seancorfield's function accordingly)
a filter-keys predicate could be something like (comp #{"name"} namespace)
...ok then
comp
was too powerful
just imagine what would have happened if someone suggested a solution based on juxt
...
@ps There's no need to leave and join channels if you find them too noisy but still want to use them - you can just right click on a relevant channel and mute it.
Hello, it seems a noob question, but how can I run a alias after another with clojure cli? Like run a alias uberjar and then my-other-task
clj -X:uberjar:my-other-task
You think tools.build will focus only on command line orchestration? I feel it will also bring along common tasks, a common config format and a standard data exchange for them, but hopefully where tasks are still just Clojure command line apps.
I didn’t say it would “focus only” on that. I just expect it to deal with chaining some sort of set of tasks — in a well-designed manner — as part of whatever it brings to the table.
Oh ya for sure.
this seems to run only the last one
I wouldn't expect it to run multiple aliases in one invocation, for one thing each alias is allowed to define the classpath differently
Only one “main” or “exec” operation can happen — and these are merged in last-one-wins form.
and unlike lein (where the lein do
command does what you describe) clj doesn't spawn multiple vms to make that possible
(I would expect tools.build
to address this sort of thing in some form since it’s such a common ask)
This is why we currently have a build
shell script at work that runs clojure
multiple times, with each group of command-line args in turn.
yes, I just would like to be able to run a alias after another
yeah, maybe I'll need to go with clj -X:jar && clj -X:my-other-task
this is related with this new lib I'm creating: https://github.com/ericdallo/deps-bin
We’d also prefer folks to show some patience when posting a question in one channel instead of cross-posting it almost immediately to another channel @ps
I'd like to sugest to user generate the jar with depstar and then call the bin with:
clj -X:jar:bin
Since you don’t need interactivity, you might suggest clojure -X:jar && clojure -X:bin
to avoid a layer of rlwrap
around each command.
FWIW, in “My Deployment Process” in the depstar
readme, I suggest exactly that sort of thing although I realize it probably won’t work on Windows(?).
alright, thanks for the help @seancorfield and @noisesmith!
hum, good point
Even worse: doing this causes noise for others because of the join/leave messages 😞
> Even worse: doing this causes noise for others because of the join/leave messages I've seen those disabled in other slacks. Personally I liked that b/c someone leaving a channel tends to have a negative connotation (however slight)
@vemv It’s very useful for Admins to see the joins because that makes it easier for us to spot folks who join and immediately start posting without getting the lay of the land. Unfortunately, we can’t easily have it enabled for Admins but disabled for everyone else I think.
I’ve turned it off for now but we (Admins) may turn it back on if it inhibits our ability to deal with bad actors.
Just write a Clojure script to do it
Like build.clj
and then clojure -X:build-task which is an alias to some function in build.clj that orchestrates whatever build you want.
Or, maybe, wait and see what tools.build
brings? 🙂