This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-07-10
Channels
- # announcements (5)
- # aws (18)
- # babashka (1)
- # beginners (81)
- # calva (7)
- # chlorine-clover (1)
- # cider (5)
- # cljs-dev (8)
- # clojure (125)
- # clojure-dev (1)
- # clojure-europe (31)
- # clojure-italy (3)
- # clojure-nl (2)
- # clojure-norway (1)
- # clojure-spec (5)
- # clojure-sweden (1)
- # clojure-uk (31)
- # clojurescript (85)
- # code-reviews (1)
- # core-async (17)
- # cursive (39)
- # datomic (16)
- # emacs (1)
- # fulcro (6)
- # java (16)
- # kaocha (2)
- # luminus (4)
- # malli (2)
- # off-topic (65)
- # pathom (3)
- # re-frame (11)
- # reagent (5)
- # remote-jobs (1)
- # rum (5)
- # sci (10)
- # shadow-cljs (24)
- # spacemacs (4)
- # test-check (3)
- # tools-deps (22)
- # xtdb (15)
I'd like to create my own edn tag, are there any good guides for doing that? The edn specification mentions that you can do it but I can't find a reference for how to do it
just use any tag you want in edn data. I assume the question is how to read it?
clojure.edn/read and clojure.edn/read-string take an opts map that includes a :readers map from tag symbol to data reader function https://clojure.github.io/clojure/clojure.edn-api.html#clojure.edn/read
ok, thanks, that's really simple. Now, if I want to provide this tag in a library that others can consume, how do I hook into the caller's reader?
if you're talking about edn reading, then it's up to the caller
if you're talking about tags in code, you can provide readers in a lib in a data_readers.clj resource
but of course :)
Does anyone developed any chat app using ejabberd or openfire using clojure? Please message also if anyone developed with other than above 2.
I'm looking at a code base which has lots of tests where the order is swapped (as opposed to what clojure.test expects): (is (= form result))
instead of (is (= result form))
. Does anybody know of a tool that will help me swap all those around?
This is quite simple in Emacs, define a macro or command that searches for "(is (="
, and then forward-sexp
and transpose-sexps
, repeat till end of file
Thanks — transpose-sexps
is what I was looking for. I wrote an Emacs function and it does 99% of the work.
clojure.test doesn't care about the order, it doesn't even care if you use =
, it just tells what form failed and what was actually present
(ins)user=> (is (= :a :b))
FAIL in () (NO_SOURCE_FILE:1)
expected: (= :a :b)
actual: (not (= :a :b))
false
(ins)user=> (let [some-random-value nil] (is some-random-value))
FAIL in () (NO_SOURCE_FILE:1)
expected: some-random-value
actual: nil
nil
perhaps some other tool you are using is making extra assumptions?
https://clojure.github.io/clojure/clojure.test-api.html
There's a notion of expected
and actual
. API usage is assumed to be = expected actual
and not the opposite
Failure to follow this convention can lead to confusing reports, if a test fails
There's further evidence of this fact in that https://github.com/magnars/kaocha-noyoda exists.
expected and actual are your input form and the result
this has nothing to do with =
, which is
has no special cases for
koacha cares, clojure.test doesn't
you still don't get it: expected and actual are the same form, before and after evaluation
(ins)user=> (let [some-random-value nil] (is some-random-value))
FAIL in () (NO_SOURCE_FILE:1)
expected: some-random-value
actual: nil
expected: the form (`some-random-value`) actual, the evaluated result (`nil`) - clojure.test isn't using =
and doesn't care which part of an equal form was your input vs. a constant, they could both be inputs and no constants for higher order testing
your mental model of clojure.test is wrong
Some people (probably people coming from imperative languages where =
is assignments) have previously learned "yoda testing" as it avoided accidental assignment by putting an rvalue on the left. This is a style question and has nothing to do with what clojure.test expects.
IDK. Could be, but also different people have recommended = expected actual
order to me over the years. I'm also quite sure that some failure reports were confusing when not honoring this order.
(...maybe the confusion has more to do with the person reading it than with any reporting/macroexpansion)
the failure report treats the whole (= x y)
as a single element, if it's hard to read it's because you and the author disagree about where x and y go
it's a style question and has nothing to do with the machinery of clojure.test, which will happily do its job even if you never call =
at all
I have tests that do (let [a (f x) b (g x)] (is (= (h a) (h b)) "f and g are h-compatible"))
- clojure.test doesn't care (but a reader might find them weird) - neither side of the comparison is constant
a more understandable example of the above
(ins)user=> (require '[clojure.test :refer [is]])
nil
(let [a (keyword "x")
b (symbol "x")]
(is (= (name a)
(name b))
"keyword and symbol are name-compatible"))
true
and failing case
(let [a (keyword "x")
b (symbol "x")]
(is (= (str a)
(str b))
"keyword and symbol are str-compatible"))
FAIL in () (NO_SOURCE_FILE:3)
keyword and symbol are str-compatible
expected: (= (str a) (str b))
actual: (not (= ":x" "x"))
false
Hello, i 'm trying to replace keys in a map for strings, Anybody has some insight of how to do it?
@ramonp.rios If you don't mind including a library or copy pasting code
the code to do it by hand also works, and is a one liner
(into {} (map #(update % 0 name)) m)
I'd even argue it's idiomatic
thank you all for the insights 😄
one way that stringify-keys is better than map-keys or my one liner, is it ignores all the non-keyword keys and leaves them as is
Stringify-keys resolves my problem
I was creating a excel file but the headers are filled with keywords instead of the name of the keyword
another option is to disable the option that created the keywords in the first place, IMHO clojure devs are over-eager to turn outside input into keywords
Anyone know what's going wrong with my integrant configuration here. I use aero with integrant and I am having trouble doing a merge of a normal map with an integrant key.
{:ig/system
{:worker-operator.client/client {}
:worker-operator.monitoring/web-server #merge [{:port 8081}
#ig/ref :worker-operator.client/client]}}
:worker-operator.client/client successfully builds a map on startup containing {:client ...}
Unfortunately I can't get the #merge
to work.
Seemingly in the order displayed, I get the map {:port 8081, :key :worker-operator.client/client}
as config to monitoring/web-server.
If I swap the order [#ig/ref :worker-operator.client/client {:port 8081}]
then I get {:client ...}
into monitoring/web-server as I want but it's then missing the port
key.Might be important that I have
(defmethod aero/reader 'ig/ref [_ _ value]
(ig/ref value))
as for that ig/ref tagrealising it probably isn't possible to combine them in this fashion since one requires the information upfront and the other is resolved later, probably should have been in #beginners mb!
Hiya! Does anyone know if there is a way to have test.check report which generator failed in this case?
ERROR in (some-test) (generators.cljc:435)
Uncaught exception, not in assertion.
expected: nil
actual: clojure.lang.ExceptionInfo: Couldn't satisfy such-that predicate after 100 tries.
{:pred #object[clojure.spec.alpha$gensub$fn__1876 0x56930e8b "clojure.spec.alpha$gensub$fn__1876@56930e8b"], :gen #clojure.test.check.generators.Generator{:gen #object[clojure.test.check.generators$such_that$fn__804 0xda5ceeb "clojure.test.check.generators$such_that$fn__804@da5ceeb"]}, :max-tries 100}
at clojure.test.check.generators$fn__801.invokeStatic (generators.cljc:435)
clojure.test.check.generators/fn (generators.cljc:434)
clojure.test.check.generators$such_that_helper.invokeStatic (generators.cljc:425)
clojure.test.check.generators$such_that_helper.invoke (generators.cljc:419)
clojure.test.check.generators$such_that$fn__804.invoke (generators.cljc:478)
clojure.test.check.generators$gen_fmap$fn__674.invoke (generators.cljc:59)
clojure.test.check.generators$call_gen.invokeStatic (generators.cljc:43)
clojure.test.check.generators$call_gen.invoke (generators.cljc:39)
clojure.test.check.generators$such_that_helper.invokeStatic (generators.cljc:427)
clojure.test.check.generators$such_that_helper.invoke (generators.cljc:419)
That test uses a tree of generators, and fails < 1% of the time, so tracking down the failing generator is difficult.the name of the fn is there, but it's auto-generted - probably #(...)
or (fn [] ...)
- maybe you could strategically rename (fn [] ...)
to (fn some-name [] ...)
oh wait no, it was generated inside gen-sub
I read it wrong
I haven't dug into the test.check source yet, but maybe I can modify it somewhat to give me more info
there might also be some trick for adding tap>
to each generator (and attach an identity generator with an identify fmap as needed), then using an add-tap that stores the contexts in order, and see which one came in last at time of error
but that's still indirect, and quite hacky
That's not a bad idea! I don't mind a hack if I can find the offending test. If that works, I'd have this in my toolbox for next time. Thanks @noisesmith! Also, good to talk to you, it has been a while :)
ditto
I've implemented my own datastructure, a multiset, and I've learned a lot about tagged literals and implementing clojure protocols by doing it.
Everything works exactly how I'd like, except when I try to use my datastructure from a new namespace
here's the repl example:
(ns my.multiset)
;; => nil
#mset [1 2 3]
;; => #mset [1 2 3]
(multiset [1 2 3])
;; => #mset [1 2 3]
(ns my.other)
;; => nil
(require '[my.multiset :as mset])
;; => nil
#mset [1 2 3]
;; => Syntax error (IllegalArgumentException) compiling fn* at (*cider-repl projects/paragon:localhost:33015(clj)*:0:0). Unable to resolve classname: IPersistentMap
Where is that syntax error come from? The only place I reference IPersistentMap is in the deftype:
(deftype Multiset [^IPersistentMap meta
^IPersistentMap multiplicities
^int size]
,,,)
And my reader function is really simple, it's just (defn multiset-reader [x] (multiset x))
I forget if this is still a thing with current versions of clojure, but older versions for a long time required type hints for return values to be fully qualified to work correctly
the metadata would be on the var
{:arglists ([] [s]),
:doc "Create a multiset from a sequence",
:line 124,
:column 1,
:file "/my/multiset.clj",
:name multiset,
:ns #namespace[my.multiset]}
what sort of stuff should I be looking for? This is my first time peering behind the curtain of clojure datastructures, so I'm fumbling through
the idea is you want to isolate which part of the repl the error is coming from: read, eval, or print
so the above returns nil
to be printed, so if you don't get an error with that, but you do with #mset [1 2 3]
you know the error comes from printing (or even technically after printing, which would be where some middleware might be trying to mess with things)
Ok, so I bounced my repl for the first time in a few days and found some issues. Those are cleared up now and I'm still getting the same error. Running your do-block above blows up, so I think the conclusion there is that it is a problem with the reader
@datran Since you have CIDER / nREPL in play, I would try the exact same REPL session with a plain ol' console REPL -- using clj
rather than lein
-- just to see if this is a problem with nREPL or CIDER.
If the same REPL session that fails via CIDER works via plain lein repl
with you typing stuff in, it's a CIDER issue. If it fails in lein repl
but works in clj
then it's nREPL.
the way to isolate that would be something like (read-string "#mset [1 2 3]")
but you'll need to make sure read-string understands your tag and I forget the details of doing that
When I run it through the edn reader, things are fine: (clojure.edn/read-string {:readers {'mset mset/multiset-reader}} "#mset [1 2 3]")
;; => #mset [1 2 3]
When I run in a plain clj repl, it still blows up:
clj
Clojure 1.10.1
user=> (require '[paragon.multiset :as mset])
nil
user=> #mset [1 2 3]
Syntax error (IllegalArgumentException) compiling fn* at (REPL:0:0).
Unable to resolve classname: IPersistentMap
@datran did you try @hiredman’s earlier suggestion of changing the type hints to fully-qualified versions, with clojure.lang.IPersistentMap
etc?
the compiler, when figuring out how to embed your type in bytecode, is choking on the type hints
I forget again, but deftype in general might not like it if you type hint non-primitive fields, but it has been a while
ah, I was thrown by your reference to hinting a "return value", since the only type hints I had were for the inputs
did you include the type hints because you were correcting reflection warnings or just adding them?
https://clojure.atlassian.net/browse/CLJ-252 must be what I am thinking of, not exactly related
is there any info about doing concurrent work inside of a transaction w/ Clojure STM?
like would it be reasonable to schedule work within a transaction on a thread pool or something similar to that?
The stm is specifically designed to work with agent sends - it delays sends until the transaction completes
Generally, txns will be retried so you should not do any other kind of io
that's very useful for me actually, but not quite what I was originally thinking of
what I'd like to do is split up the work done to calculate the ref values within a transaction, across some threads
so say I have 20 refs that I want to alter in a transaction. I split that work up across 4 threads, and if any of the alterations fail then it should retry or abort all of them
That’s not going to work
Or at least I wouldn’t attempt it
You’re way outside the design space for stm
Txns should be short and retryable - doing anything multithreaded seems like you’re doing this wrong. There are way more failure modes
I’m not saying it won’t work :)
I guess, the part that attracted me to STM is the transactionality. the properties that I need for my use case are: • an alteration isn’t “committed” until the end of the transaction • that a failure causes the whole transaction to fail • safe to use concurrently (for some definition of “safe”) in that way some of the specifics of the STM are useful but not necessary (e.g. retry on conflict)
the use case i’m working with is this idea of a graph of computations whose inputs can be changed, and then the graph is stabilized by running each computation and storing their result inside of a ref. this way, a result is only stored if the whole stabilization succeeds. one of my goals is to allow parallelization of computations. but maybe i’ll punt on that for now
What do Clojure people think of how scopes work in https://janet-lang.org/docs/specials.html? (You can add new bindings without increasing nesting):
# Prints 1
(do
(def a 1)
(print a))
# a is not defined here, so fails
a
personally I like the distinction between global definition (`def`) and local binding (`let`), but that feels like an aesthetic preference
hey yall, is there a way to create a io/writer
that writes to a string? or does that not make any sense?
I'm trying to use csv/write-csv
to output a valid CSV line as string. I'm not using str/join
to do it because I need write-csv
to handle escaping commas for me
You could use the java class https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/StringWriter.html
I'm in the same boat as @lilactown. additionally, I'll sometimes temporarily group top level defs in a do
so that they all reevaluate together when I do eval-top-level-form in my editor. for example:
(do
(defn my-view [] ...)
(defn uses-my-view [] (my-view)))