Fork me on GitHub
#clojure
<
2020-11-28
>
Kevin09:11:03

Anyone know of a library / method to create a hash from a clojure map in both Clojure and Clojurescript? The clojure.core/hash function produces different results (CLJ vs CLJS).

borkdude10:11:28

@kevin.van.rooijen This is another one: https://github.com/arachne-framework/valuehash But I think you will get fundamentally different hashes in CLJ and CLJS due to the host platform. If you want to avoid this, maybe use a stringified cryptographic hash or something?

mpenet10:11:56

Datahike has a lib for that as well

mpenet10:11:47

That one yes

borkdude10:11:58

@kevin.van.rooijen What you can also do, if the data structure isn't that rich: encode to bencode and then crypto-hash those bytes, since the bencode representation of a map is always ordered

borkdude10:11:06

I've seen someone using that trick before

Kevin10:11:39

The datastructure can vary is size. I'm going to look at the hasch library, it seems like it does what I want

borkdude10:11:22

I wasn't talking about size, richness in types (sets, uuids, etc)

Kevin10:11:16

I'll take a look at that option as well 🙂

palo14:11:49

Hi guys, is there any library for working with timeseries ? Let’s say i have input of random epochs with data sets and want to make different aggregations in time e.g. time-1h, time-3h, time-6h, time-12h … So similar goal than Influx RP (DURATION) 🙂

jjttjj14:11:10

I've been doing stuff like this lately:

(defn last-rounded-ms [time-ms dur-ms]
  (- time-ms (mod time-ms dur-ms)))

(def series
  (->> 
    (iterate #(+ (rand-int 5000) %) (System/currentTimeMillis))
    (take 100)
    (map (fn [time] {:time time :val (rand)}))))

;;=>
;;{:time 1606574577638, :val 0.4425581456446229}
;;{:time 1606574581828, :val 0.6842765060777032}
;;{:time 1606574583114, :val 0.7802471729760035}

(->> series
     (map (fn [pt]
         (assoc pt :bucket
                (last-rounded-ms (:time pt) (* 60 1000)))))
     (partition-by :bucket))
;;=>
(({:time 1606574505069, :val 0.3325513886871063, :bucket 1606574460000}
  {:time 1606574506946, :val 0.5809867767391736, :bucket 1606574460000}
  {:time 1606574509770, :val 0.09720508907807157, :bucket 1606574460000}
  ...)
 ({:time 1606574520971, :val 0.7242463947216449, :bucket 1606574520000}
  {:time 1606574522158, :val 0.6796656790450822, :bucket 1606574520000}
  {:time 1606574527077, :val 0.26636079563117787, :bucket 1606574520000}
  ...)
 ({:time 1606574581828, :val 0.6842765060777032, :bucket 1606574580000}
  {:time 1606574583114, :val 0.7802471729760035, :bucket 1606574580000}
  {:time 1606574584050, :val 0.3131993783803969, :bucket 1606574580000}
  ...)
 ...)

jjttjj14:11:46

note the bucketing can also be done as a transducer if you're working with streaming data

jjttjj14:11:23

The xforms library let's you get pretty fancy with aggregations: https://github.com/cgrand/xforms And it's window-by-time function also is relevant here

palo19:11:22

@U064UGEUQ Thx man 🙂 this works great :thumbsup: I’m working on some prototype so this is just enough to present idea (charts), ideally i will deal with RP directly in influx/prometheus later 😉 .. Now the dataset is just raw select from RDBS ..

👍 3
Max15:11:17

I just saw the https://github.com/leonoel/cloroutine and https://github.com/leonoel/missionary libraries go by, both seem like they push Clojure in new and interesting directions. But I’m a newbie, I’m not super familiar with the state of the Clojure ecosystem. I’d be interested in the opinions of those with a little more experience. What do you think?

leonoel16:11:54

cloroutine is not really a new idea, in fact it's heavily inspired by core.async 's implementation of go blocks. cloroutine adds some optimizations and provides cloning. missionary is a clojure incarnation of what is currently known as reactive programming (althought I prefer to just call it functional programming), which is quite popular in java/scala but not so much in clojure ecosystem (for now !), possibly because Rich himself expressed some doubts about this paradigm and chose to invest on CSP instead. Compared to e.g RxJava, missionary leverages coroutines instead of monadic composition and aims to fix some legacy weirdness inherent to its internal protocol (now standardized as Reactive Streams). FYI #missionary exists if you want to discuss it further

Max17:11:49

What interests me about cloroutine is that it seems like it paves a path towards Lisp’s conditions in a way that core.async does not. For example, I don’t know how I’d implement https://github.com/ajnsit/concur using core.async, but I can see a clear path with Cloroutine

Max17:11:51

Is that impression accurate? It’s very possible I’m missing something

hiredman18:11:48

If you want a way to do something with continuations in a language without continuations, you may want to look at the continuation monad

hiredman18:11:29

https://blog.mattbierner.com/the-delimited-continuation-monad-in-javascript/ is an example of the cont monad in js (most examples are in haskell), in clojure you can pretty up the syntax a fair bit with macros

leonoel18:11:51

all of these concepts are equally powerful, you can basically take any monad instance and write a direct-style syntax on top of it using continuations or coroutines @U01EB0V3H39 here's a case of hijacking of core.async's coroutine engine to implement algebraic effects https://github.com/brandonbloom/cleff

Max20:11:50

Awesome, thanks!

lilactown16:11:32

they seem fascinating, potentially useful. I find the syntax pretty inscrutable but that's probably just a lack of familiarity

lilactown16:11:51

I've used core.async and manifold in production, which are similar to cloroutine and missionary. I would love to see a comparison in approaches. It seems like the author is still experimenting, based on the READMEs, so I probably wouldn't use them in production until they stabilized