This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-04-01
Channels
- # announcements (19)
- # asami (4)
- # babashka (34)
- # beginners (137)
- # calva (22)
- # cider (4)
- # clj-kondo (25)
- # cljs-dev (4)
- # clojure (67)
- # clojure-australia (1)
- # clojure-berlin (1)
- # clojure-europe (35)
- # clojure-germany (3)
- # clojure-nl (5)
- # clojure-serbia (3)
- # clojure-uk (8)
- # clojuredesign-podcast (2)
- # clojurescript (11)
- # conjure (56)
- # data-oriented-programming (1)
- # datascript (1)
- # datomic (6)
- # deps-new (11)
- # eastwood (1)
- # fulcro (11)
- # honeysql (48)
- # inf-clojure (1)
- # jobs (1)
- # joker (6)
- # lsp (26)
- # malli (2)
- # meander (3)
- # off-topic (48)
- # pathom (4)
- # polylith (4)
- # re-frame (19)
- # releases (2)
- # remote-jobs (1)
- # rewrite-clj (127)
- # shadow-cljs (6)
- # spacemacs (3)
- # tools-deps (43)
- # xtdb (16)
I have a collection of maps, I want to find the maximum :timestamp across all elements...
something like (first (sort-by val > :key map))
gets the result...
Neat! Can you explain how to think about the problem to get that solution?
well from your description, it’s like max
but you want some way to get that inner timestamp, so you can use max-key
to supply that
yep that's exactly right. i don't really get how max-key works, but i will stare at it more
that's very clean 😄
Ah I think I get it. max-key is like max and get-in smashed together
but we need apply... because why?
Ah i see
righteous. thank you
just think of max-key
as max
, but you can supply a function to calculate the value which it’ll use to find the maximum
😄 i noticed but took it as a friendly exercise to the reader
thanks a lot. if you're interested in what i'm tinkering with right now, i'm trying to apply this "send over only database deltas :since-timestamp" principle, so every so often the client says "i have up to timestamp ts-val" and the server checks the database of entries and returns things newer than that. pretty simple. i got the idea from @tonsky, "For dataset sizes up from few hundred kilobytes you start to feel need to transfer deltas instead of entire value." https://tonsky.me/blog/datomic-as-protocol/
You might - if you’re not married to Datomic - also want to take a look at Crux. It’s a bitemporal database that might fit your specific need well.
Hi there. I’m stumbling across something and I’m not sure what’s going on. I have this block of code:
(case (class (OffsetDateTime/now))
java.time.OffsetDateTime "a"
String "b"
false)
and somehow that’s evaluated to false
even though I’m expecting it to be true
. Am I doing something wrong here? Thanks in advance.The test-constants are not evaluated. They must be compile-time literals, and need not be quoted
...
All manner of constant expressions are acceptable in case, including numbers, strings,symbols, keywords, and (Clojure) composites thereof.
the short answer is you need something like cond
or condp
along with instance?
Ah I see. I’ve always thought classes themselves are constants. Thanks @hiredman @smith.adriane
classes are not constants (and not even unique in the JVM - every classloader can potentially load their own version)
case
on class name is occasionally useful
(assuming you have a finite set of concrete classes to check)
Thanks @alexmiller. condp
gives me the expected behaviour so things are finally working for me now 😅
Can I type hint a keyword? What is the incantation? I've tried ^clojure.lang/Keyword kw
You shouldn’t need to do so
Thanks! I should start looking at the Clojure internals someday.
Same question for {}
. I've tried ^java.util.Map
.
Uh-oh: java.lang.IllegalArgumentException: Unable to resolve classname: clojure.lang/PersistentHashMap
. Might there be something wrong with my setup?
No. I wasn't using all dots.
Why the difference?
The below function will - worst case - be called umpteen gazillion times:
(defn to-path [^String file ^clojure.lang.Keyword rule ^clojure.lang.PersistentHashMap wildcards]
(let [rulename (name rule)
wc (zipmap (map name (keys wildcards)) (vals wildcards))
wc (->> wc sort flatten (clojure.string/join "/"))]
(clojure.string/join "/" [rulename wc file])))
So I am hoping type-hinting will improve the performance a little.Also, to be “correct” type hint in all cases, use clojure.lang.APersistentMap:
(instance? clojure.lang.PersistentHashMap {})
=> false
(instance?
clojure.lang.PersistentHashMap
(into {} (comp (partition-all 2) (map vec)) (range 100)))
=> true
(instance?
clojure.lang.APersistentMap
{})
=> true
(instance?
clojure.lang.APersistentMap
(into {} (comp (partition-all 2) (map vec)) (range 100)))
=> trueI wouldn’t bother with such things unless you’re really chasing performance; if you really care about performance, use YourKit (but it’s a paid tool); you can almost never guess where your bottleneck is; it’s probably where you least expect it.
But this is a cheap optimization (in terms of readability and programmer effort) which might matter a lot.
Those type hints won’t do anything
Type hints are only useful in turning an ambiguous java interop call into an unambiguous one (to avoid reflection). There are no interop calls in this method, so those type hints are useless and ignored
Had no idea! Thanks
you generally never should make an interop call on types that are part of Clojure (you should use normal Clojure invocations to interact) and thus it’s very unusual to type hint Clojure classes
If you were to type hint a Clojure map, the correct interface is IPeraistentMap (not the APersistentMap abstract class - not all maps extend from that)
re: interfaces, thanks for correcting my ignorance 🙂 @alexmiller
I think I know the answer, but would be nice to know definitely: if I have map with unqualified keywords, can I write a spec for those values mapped by those unqualified keywords? Or if I want values to be validated I need to put them in maps with qualified keywords?
(s/keys :req-un [::alias/foo] :opt-un [::alias/bar])
with (s/def ::alias/foo …) and (s/def ::alias/bar …)
will be able to validate maps like this
{:foo … :bar …}
Hi, I have java lib with constructor which i have to use, and this constructor requires instance of java's ExecutorService as an argument, what wil be the best way to use this lib from clojure?
Hi 🙂
I want to use browse-url
function on a windows OS in order to rederact to diffrent page.
Is it possible to convert
to clojure.java.browse
?
yes that worked.
(browse-url (str (
tnx :)
As far as I know, there’s no function like partial
that can return a function given all of the arguments so I’m using def
with an anonymous function like this:
(def fancy-now #(str "the time is now " (new java.util.Date)))
(fancy-now)
Is this the right way to do this? Like the example, my function is an “action” in that it depends on external conditions.I know it works, I’m just wondering if it’s idiomatic or if I’m missing a bigger picture idea.
Can’t you just define a fn that takes no args and then invoke it?
(defn fancy-now []
(str "the time is now " (new java.util.Date)))
Or if you want to define it in-line:
(defn my-fn-that-uses-now []
....
(str "the time is now " (new java.util.Date))
....)
Or if you want to you can ‘store’ the result in a var in a let:
(defn my-fn-that-uses-now []
(let [now (str "the time is now " (new java.util.Date))]
(fn-needing-now now)
....)
As an example say you have a fn that returns a map that needs to include the results of that str
you might do something like this:
(defn my-fn-that-uses-now []
....
{:name name
:age 23
:now (str "the time is now " (new java.util.Date))})
ok, my example wasn’t complex enough for what I’m doing but your comments helped me sort it out. It’s more like the following (which I can now use partial
for):
(defn fancier-now
[greeting time]
(str greeting "the time is now " time))
(def fanciest-now (partial fancier-now "Hello, "))
(fanciest-now (new java.util.Date))
In my real use-case, I can’t pass in (new java.util.Date)
because I’m actually doing this for dependency injection and I don’t want fanciest-now to need to know about java.util.Date
.
I don’t think I understand why you need the def
for fanciest-now
or the context of the invocation of fanciest-now
so hard to give advice.
Also dependency injection is not something we really do in Clojure. Tend to just use fn’s passed around in data if required.
However, not sure if it’s useful but you can define a high order fn that returns a fn if required like so:
(defn fancier-now
[greeting]
(fn [time]
(str greeting "the time is now " time)))
(let [fanciest-now (fancier-now "Hello, ")]
(fanciest-now (new java.util.Date)))
I used the let
there simply to define the var for the anonymous fn returned from fancier-now
but I could have used a def
like you did i.e. (def fanciest-now (fancier-now "Hello, "))
I think there are probably more idiomatic ways to accomplish what you are trying to do but I don’t have enough context to suggest any.
Sorry for the slow replies, I have to think about the suggestions and my use case. The context seems somewhat complex to me so I didn’t want to trouble anyone with it but here’s as short as I can describe it:
• I’m interfacing a chip via i2c to read environment data
• I’m waiting for interrupts to know something changed which I read via gpio
• when there’s a gpio interrupt, I read the i2c chip for data
• I have a namespace for using gpio to information-hide those details
• I have a namespace for i2c to information-hide those details
• Since this is all asynchronous in nature, I have to run this all from an async/go routine
So the code goes something like this:
(def chip-context (chip/setup-chip …))
(async/go (gpio/handle-events
chip/event-handler
chip-context
deserializer
event-channel
…))
So when I say I’m “injecting dependencies” I only mean I’m passing in functions and data to the handler. This whole question is oriented around how I can pass the handler function and chip-context data in a way that seems coherent. I was taking the approach of partially applying the handler to already have the chip context, deserializer and output channel but maybe a map is better.
Is there some trick to get in macro in which stage it been used?
(defmacro foo []
(cond
cljs? 'cljs.core.async
clj? 'clojure.core.async))
something like this ^maybe stage is the wrong term here 🤷 but I don’t know the right one
so far I found the difference in &env
between clj and cljs but not sure if this is something that I can rely on
are you looking for reader conditionals? https://clojure.org/reference/reader#_reader_conditionals
#?(:clj Double/NaN
:cljs js/NaN
:default nil)
not really, I have macro.clj where I define some macro and app.cljc where I want to use it. But the code generated by the macro should be different depending on target of compilation (clj or cljs)
so far I added this
~(if (contains? &env :js-globals)
'cljs.core.async/go-loop
'clojure.core.async/go-loop)
but it looks too uglyand I think the fact that there is :js-globals in &env is not really reliable
https://github.com/cgrand/macrovich/blob/master/src/net/cgrand/macrovich.cljc#L23-L28 looks like it is doing exactly the same thing )
thanks!
Could someone point me to where I can find the difference between <!
and <!!
in core/async
? I'd google it myself but its kind of hard to get google to not ignore that syntax.
One is blocking, the other is not.
@seancorfield But the 'non-blocking' one says: "Will park if nothing is available."
Parking is not blocking.
Blocking will block a thread. Parking just switches to another go
block to continue executing something else.
Okay, what is parking? (I was under the impression that parking
was like blocking but for green-threads.)
> Blocking will block a thread. Parking just switches to another `go` block to continue executing something else. Hmm...so what happens then when it comes back to the original task that 'parked', and still didn't have something available?
It won’t unpark until there is something to take.
go
blocks are “collaborative” in that sense.
Ah, wait, by parking, vs blocking, are you meaning: "parking = freezing a go-thread" and blocking = freezing an os thread"?
No. Parking doesn’t freeze anything.
And if so, then it seems like clojurescript wouldn't have <!!
, at least not without webworkers, since there would be only one os-thread.
There is an implied event loop, which is effectively a big queue of functions which are cooperatively yielding control to the thread driving the event loop
the go macro is similar to the javascript await, python await, etc
execute to <here>, then yield control from this current execution back to the event loop so something else can run
the "park" is similar to "yield execution control back to the event loop. wake me up when something on the other side of the park operation has placed something in that channel i'm waiting on, and wake me up after that"
I’m pretty certain ClojureScript does not have <!!
or >!!
@U050G2TQJ
@U38AEDBQU That also makes a lot of sense.
the main benefit is that in either concurrent async or parallelism threading mode, you are using a queue idiom that works the same on both
with the channel (chan) being the queue
Well, if all your go
blocks are parked, then it “freezes” (until another thread changes the state of the channels in a way that something can unpark).
The TL;DR is that core.async
is really hard to use correctly and can be a pit of vipers for beginners 😐
> Well, if all your `go` blocks are parked, then it “freezes” (until another thread changes the state of the channels in a way that something can unpark). I mean, that sounds an awful lot like blocking to me. I suspect I'm missing something here.
parking == no thread tied up (there is a callback attached to a channel; when the callback fires, the go block is resumed)
I think it’s misleading to think of core.async
even as “green threads”. It doesn’t have lightweight threads of any description (in ClojureScript): it has collaborating sequential processes (CSP of old).
(in the Clojure version, go
blocks run in their own small thread pool as I recall)
Ah, well given that my goal is to await
on a function that takes a callback, probably not quite what I want.
Is it a javascript ES7 await
that you need? In that case you could go with plain-js and use the promise constructor to turn the function taking a callback into a javascript promise that you can await.
That would create a promise that instantly resolves with a value. I was talking about https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise the constructor