This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-26
Channels
- # announcements (1)
- # aws (6)
- # babashka (1)
- # beginners (109)
- # calva (22)
- # clj-kondo (21)
- # cljsrn (1)
- # clojure (68)
- # clojure-europe (41)
- # clojure-nl (2)
- # clojure-uk (5)
- # clojurescript (7)
- # core-logic (1)
- # data-science (4)
- # datomic (1)
- # events (1)
- # fulcro (25)
- # gratitude (1)
- # juxt (4)
- # keyboards (1)
- # malli (5)
- # minecraft (3)
- # missionary (9)
- # music (1)
- # nextjournal (7)
- # off-topic (7)
- # polylith (31)
- # re-frame (3)
- # reveal (7)
- # ring (11)
- # shadow-cljs (1)
- # spacemacs (4)
- # tools-build (5)
- # tools-deps (5)
- # xtdb (25)
Hi all! Does anybody use Google Guava with Clojure? In particular, I am thinking of using their https://github.com/google/guava/wiki/RangesExplained api and I would like to know if there is any Clojure wrapper out there already (or if it's not worth having it).
What use case are you aiming at? You can wrap Clojure's range with with some set-like behavior to get both
I need to basically check if my ranges are contiguous and/or have overlaps.
yeah well I have intervals and I basically need to check for existing gaps
I actually really like how they are showing at the REPL
(interval->guava-range i1)
#object[com.google.common.collect.Range 0x56a8dbf7 "[1.0..10.0)"]
If I understand correctly interval trees are trees that have intervals as keys?
(will google more, thanks for the hint)
Cheers Also see https://github.com/dthume/data.interval-tree
yeah it does not fulfill my use case, we have open/closed bounds (in Guava called endpoints) but thanks for the link!
You can also start from something like this
(defn -range
[{:keys [min max]}]
(let [^clojure.lang.Range r (range min (inc max))]
(reify
clojure.lang.IPersistentSet
(contains [_ k] (and (< k max) (< min k)))
clojure.lang.IChunkedSeq
(chunkedFirst [_] (.chunkedFirst r))
(chunkedNext [_] (.chunkedNext r))
(chunkedMore [_] (.chunkedMore r))
clojure.lang.ISeq
(first [_] (.first r))
(next [_] (.next r))
(more [_] (.more r))
(cons [this o]
(if (.contains this o)
this
???)))))
i’d say not worth having it for your problem. probably worth someone doodling up a cljc library if someone else has the same problems
I know I could implement this myself but Google Guava fits the bill and it's reliable - I just wished it was packaged as separate jar so that I could use only what I need
i'm curious about the (potential) differences between run!
, doseq
, and mapv
when processing lists of side-effecty things.
doseq and run! don't return anything, while mapv does. doseq has a bit of a DSL to support conditions and nested loops, run is straightforward
i have this HTTP connection which returns data intermittently over time. since the response class implements Iterable
, i can seq
over it to process the data when it's available. but i'm seeing some curious differences between these three options.
there's some logging in there when data comes in. with mapv
and run
I see the log immediately as expected. with doseq
i only see everything at the end, when the connection is terminated (this is on a several minute interval).
Sounds like chunking. I don't recall off the top of my head but I think calling seq on iterable creates a chunked seq
What would be a good name for the key :example/key
in {:example/keys [a]}
- we already have :keys-destructuring true
for a
to indicate that keyword was used for keys destructuring, but we need a name for the other one too
Bikeshedding. When writing an api I quite like the pattern of a function that takes a map and assoc’s its result onto it under some sensible key as return value. Alternatively you could just return the result and let the caller add it if desired. Any preferences?
It's often convenient and definitely depends on the case but personally I'm not sure it's good design. Like you said, why not return just the value you're changing and let the consumer do whatever they want (assoc or something else)?
It depends on how the function is expected to be used. I find returning an augmented map works really well for functions in a threading pipeline. But if a function is intended to be used standalone, a straightforward return value makes sense a lot of the time.
For example, at work we have a number of image-processing functions that are intended to be threaded, so they all return their input hash map with "results" assoc
'd in.
Yes, I’m assuming the function is useful in a threading pipeline. My main problem is this:
(-> some-map
some-operation
(assoc :some-key (some-func ??)))
I don’t know of any clean way to reference the output map of some-operation
there. at->
would work hereAlso, when I'm not sure about future extensions of the argument and result value, in my experience, taking and returning a map is the best bet.
Maybe I'm overthinking it but my "worry" is that computing the value and enriching a map might be a kind of complecting. Like, maybe it would be better to have x functions that each computes a value and an extra function that does just the enriching by calling the others and assoc'ing their result. But yeah I agree that returning a map is often more convenient!
There's also a performance consideration. Very low level functions might not have the luxury of creating maps for each results.
(-> some-map
...
(as-> m (assoc m :some-key (some-operation m))
...)
If that seems like a "common" pattern with certain functions, I'd say it's a good argument for making them return a hash map of their input + their output.Or at least writing a wrapper function: (defn with-result [m k f] (assoc m k (f m)))
so you can do:
(-> some-map
(with-result :some-key some-operation)
...)
I like the with-results function. When your first reaction is ‘I should have though of that’ you know it’s good 🙂
Generally, I think it’s nicer not to assume any composition in your value-producing fn, but let your callers do the composition. I don’t have a no hard rule, though.
returns ; (err) Could not locate clojure/tools/deps/alpha/repl__init.class, clojure/tools/deps/alpha/repl.clj or clojure/tools/deps/alpha/repl.cljc on classpath.
Work on add-lib can be found here; https://github.com/clojure/tools.deps.alpha/tree/add-lib3
I don't think it was ever on master
:thinking_face:
I assumed it was as I saw it in Seans' presentation on clojure repl development (clojures' superpower)
Revising my thinking: defprotocol implemented as defrecord. Need to know how to call that record; There is a gist
https://gist.github.com/KnowledgeGarden/2dc4d57ac59ba856584fb59f206e957e
which is the state of the code - which varies; depending on which code example or document you read, you either need a "this" or you don't. I have yet to nail down that heuristic.
But, the primary issue is making the API's put-proxy
visible to call from elsewhere. Right now, it's like a mock trial: no real proxy or database (which will be Datahike) is in play. Trying to sort this out.
Modified the code in core.clj to make an instance of the record: `
(defn foo
[]
(let [db (DhPgBackside "database")]
(db/put-proxy "foo"))
(println "Hello, World!"))
`
at which point Intellij insisted that the class DhPgBackside
could be imported, so I allowed that; now it gets a ClassNotFound exception (even if I put (:gen-class) in that file.I left a comment - maybe that clarifies things up. Btw, naming the namespace and record class with the same identifier is really confusing, that's why your IDE is confused perhaps. The comment: https://gist.github.com/KnowledgeGarden/2dc4d57ac59ba856584fb59f206e957e#gistcomment-3976260
@U0JEFEZH6 that solved the issue and, what's more, gave me a much clearer picture of what's going on than I could find in books. Many thanks 👍
Hello, I would like if there is a clever way to implement this…
(defn keys-sequence [ks]
(let [index (ref -1)]
(fn []
(let [next (dosync (ref-set index (inc (deref index))))]
(nth ks next)))))
(def ks (keys-sequence [1 2 3 2 1]))
;;(ks) => 1
;;(ks) => 2
;;(ks) => 3
;;(ks) => 2
;;(ks) => 1
It is not exactly like (cycle [1 2 3 2 1])
as it is not a lazy sequence, it is just a function with state, any idea of a already existent function for that?Simpler, I think
(defn pull
[^Iterable coll]
(let [it (.iterator coll)]
(fn [] (.next it))))
like so
(defn pull
[^Iterable coll]
(let [it (.iterator coll)]
(fn [] (when (.hasNext it) (.next it)))))
@UK0810AQ2 can you do that without Java interopt
How about this with an atom
?
dev=> (defn keys-sequence [ks]
#_=> (let [data (atom ks)]
#_=> (fn [] (let [[[x] _] (swap-vals! data next)] x))))
#'dev/keys-sequence
dev=> (def kf (keys-sequence [1 2 3 2 1]))
#'dev/kf
dev=> (kf)
1
dev=> (kf)
2
dev=> (kf)
3
dev=> (kf)
2
dev=> (kf)
1
dev=> (kf)
nil
dev=>
Technically, that's [[x & _] _]
-- swap-vals!
returns the old value and the new one, and you only care about the first element of the old value.
I guess this would be nicer:
dev=> (defn keys-sequence [ks]
#_=> (let [data (atom ks)]
#_=> (fn [] (ffirst (swap-vals! data next)))))
@U14K4HW3T You don't need ref
unless you are trying to coordinate multiple updates in a single "transaction". ref
is almost never needed, to be honest.
@UK0810AQ2 to emulate a sequence of line-read
in a test.
@U04V70XH6 cool, the last code is much better, thanks for share it. One question, isn’t var a better option in this context? Just a fake sequence for a unit test…. Thanks…
What do you mean "var"?
@UEENNMX0T possible, but outside of cljc compatibility I'd reach for an iterable here
@U04V70XH6 something like this:
(defn keys-sequence [ks]
(def index -1)
(fn []
(let [next (alter-var-root (var index) inc)]
(nth ks next))))
I'd say you shouldn't write your code to begin with in such a manner which is coupled to line read. You have an initial state and a series of inputs. Do you need to model the source of inputs for it to work? (f [state line]) -> new-state Then you can even test this flow in a loop or reduce. Separate the source of inputs
Yep, I guess my problem is to understand simple concepts. Just for illustrate metaphorically the conceptual problem. Imagine I have a simple calculator, and it accumulate values like this.
(defn calculator [ns]
(reduce + 0 ns))
How can I work with an infinite but lazy source in ns? ex: '(input-line, input-line, … , input-line)
and terminate when the reduce value is x
?
For this I have created a recursive function, like:
(defn calculator-fn [acc, n]
(if (= acc 10)
acc
(recur (+ acc (first acc)) (read-line))))
I am not sure how really extract the read-line and treat that as a regular collection so use it as ns
in the first example. Notice that (read-line)
is infinite here an will terminate when (= acc 10)
Did you get the whole ideia? who use reduction with a streams of data..!?
Thanks.Okay, after some studies, I realise I can do it this way:
(defn acc[a c]
(let [sum (+ a c)]
(if (>= sum 10)
(reduced sum)
sum)))
;; user real inputs
(reduce
acc
0
(map #(Integer/parseInt %) (repeatedly read-line)))
;; unit test
(reduce
acc
0
(range 9 11))
Any way to improve it?
Any way to weed out the acc
function?
Maybe transducer, but not sure yet …Re: your "var" example -- having def
inside a function is pretty much always wrong. And treating Clojure Vars like mutable "vars" from other languages is definitely not the approach you should be considering -- it's very non-functional.