awesome
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...
(apply max-key :timestamp your-coll-of-maps)
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?
because max-key takes a number of args when you call it
again, it’s like max
you’d call (max 1 2 3)
, not (max [1 2 3])
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
(= (max 1 2 3) (max-key (fn [v] v) 1 2 3) (max-key identity 1 2 3))
very illustrative example and REPL'able! thank you
I missed a paren at the end so if you ran it, it may not return 😅
😄 i noticed but took it as a friendly exercise to the reader
you solve the problems i balance the parens everyone feels smart 😛
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/
I’m also playing around with datomic at the moment. Seems really cool.
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.case takes unevaluated constants
String and java.time.OffsetDateTime are symbols that evaluate to classes
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
Same question for {}
. I've tried ^java.util.Map
.
(let [^clojure.lang.PersistentHashMap m {}]
(assoc m :a 42))
Thanks 🙂
(let [^clojure.lang.Keyword k :a]
k)
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?
It’s a Java class; forward slashes are for accessing static methods
(System/currentTimeMillis)
Why exactly do you need to type hint?
Generally, it shouldn’t be necessary
It’s needed mostly for performance reasons.
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)))
=> true(type {}) => clojure.lang.PersistentArrayMap
PersistentArrayMap is an optimization for small maps;
I 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.
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 …}
Thanks, not sure why I missed this when reading the docs, I could find it now easily.
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?
You shouldn’t need to do so
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)
Thanks! I should start looking at the Clojure internals someday.
re: interfaces, thanks for correcting my ignorance 🙂 @alexmiller
Hi 🙂
I want to use browse-url
function on a windows OS in order to rederact to diffrent page.
Is it possible to convert <http://java.net|java.net>.URL
to clojure.java.browse
?
(str …)
?
yes that worked.
(browse-url (str (<http://clojure.java.io/as-url|clojure.java.io/as-url> test-meow)))
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>
can help with lots of this stuff
and you can read the source to just implement in that manner or use the helpers
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.
And the api seems to be identical except the workd parking
and blocking
.
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?
doesn't*
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.
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 😐
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
> 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.
blocking == a thread is tied up
execute to <here>, then yield control from this current execution back to the event loop so something else can run
parking == no thread tied up (there is a callback attached to a channel; when the callback fires, the go block is resumed)
by thread I mean a real java.lang.Thread
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"
@ghadi Okay, so then ya.
For clojurescript you wouldn't ever use <!!
without webworkers.
I’m pretty certain ClojureScript does not have <!!
or >!!
@leif
(And parking is blocking for green-threads.)
(Which are cooperative threads.)
Or at least I'm meaning that.
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, okay, this makes sense.
@saeidscorp That also makes a lot of sense.
Mmm...fair.
Okay, I think I have my answer now though, thanks. ^.^
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
TLDR, use <!
in clojurescript, as its the only option. 🙂
Because it only has one os thread (again, sans webworkers)
you can use take!, but you have to pass it a callback
with the channel (chan) being the queue
Ah, well given that my goal is to await
on a function that takes a callback, probably not quite what I want.
(I'd use <p!
, but its not a promise, its just a CPSed function.
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.
@alpox Using something like Promise.resolve
?
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
Ah, okay.
The pattern for wrapping a callback function would look about something like this:
(defn do-something-async [param-1]
(js/Promise.
(fn [resolve reject]
(my-fn-with-callback
param-1
(fn [err result]
(if err
(reject err)
(resolve result)))))))