#clojure logs

2017-06-30

00:05TEttingerrandom_numbers: SecureRandom does that
00:05random_numbersTEttinger: I see.
00:06TEttingerSecureRandom is, as it probably should be, massively slower than j.u.Random
00:10kenrestivo/dev/random vs /dev/urandom
00:11random_numbersMakes sense.
00:19TEttingerthere are a ton of advantages to SplittableRandom's algo though.
00:19TEttingeryou get leap-ahead/leap-back in constant time
00:20TEttingerSplittableRandom may not expose it? but anything it does can be done by you
00:22TEttingerif you normally called the version I gave like splitMix64(state += 1337) , then you could jump forward 23 steps and get the result from there by doing splitMix64(state += 1337 * 23)
00:22TEttingeryou could jump back 23 steps by doing splitMix64(state += 1337 * -23)
00:25TEttingerwhat makes a generator cryptographically secure anyway, random_numbers?
00:26TEttingerI think the first criteria needs to be inability to predict future outcomes from previous ones
00:26TEttingerI think it might be good if the output is indistinguishable from true randomness with a low margin of tolerance
00:26random_numbersTEttinger: Hm, can't recall off-hand. Just recalled that reusing seeds can be unadvisable.
00:27TEttingerdepends
00:27TEttingerfor testing you need to reuse seeds
00:27TEttingereither you're testing possibly every input, or you need to reproduce failure cases
00:54xrashI have a vector of maps in the following format: [{x:2, ...}, {x:2, ...}, {x:3, ...}, ...] and I want to traverse this vector creating another vector in the format: [{x:2, items: [every item with x = 2 from the original vector]}, {x:3, items: [every item with x = 3 from the original vector]}]
00:54xrashI am struggling to get this working in a functional way.
00:55xrashI cannot not think about this as a for loop collecting stuff. :(
00:55random_numbersTEttinger: I see.
00:57jeayexrash: reduce can certainly do this.
00:57TEttingeror for I think
00:57xrashIll take a closer look on those.
00:57TEttingerwhere you say every item, do you mean the whole map {x:2, ...} or just the ... there ?
00:58TEttingerreduce is definitely powerful but it can be tricky to get it to work cleanly, and there's often a different way
00:58xrashI think this will make no difference.
00:58TEttingerstill not sure what an item is
00:59TEttingerohhh
00:59xrashItem is the whole map, but if every map from the result vector will have the value of x, it will make no difference to me whether the resulting item will also contain nested value of x or not.
00:59TEttingermerge-with could be handy
01:00TEttinger,(doc merge-with) ;; checking for myself
01:00clojurebot"([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter)."
01:01xrashThis seems to have some relation with my case, however I will also explore reduce and for anyway as an exercise.
01:01TEttingerfor may be useful in similar cases
01:02TEttingerI think merging is the general type of thing we're looking at
01:03xrashHowever this merge-with function seems to receive several maps as different parameters, and I have a vector. Will it work with vectors?
01:04xrashAnd I want a vector as a result, not a single map.
01:06jeayexrash: https://gist.github.com/jeaye/829d0944c39de52e17214da25f08e307
01:06jeayeYou want something like that?
01:07jeayeOh, updated to show what grouped is. You can refresh.
01:08xrashAt first glance it seems exactly like it, but I will have to read a little bit to understand.
01:08xrashThanks!
01:08jeayeYou _could_ do this with one reduce, but I wouldn't without better reason.
01:09jeayexrash: I recommend taking it out of the gist and formatting it in your editor, to help understand what's going on. Feel free to ping me with questions about it.
01:14TEttinger,(mapv (fn [[k v]] {:x k :items v}) (group-by :x [{:x 2, :item "hooray"}, {:x 2, :item "yay"}, {:x 3, :item "yippee"}]))
01:14clojurebot[{:x 2, :items [{:x 2, :item "hooray"} {:x 2, :item "yay"}]} {:x 3, :items [{:x 3, :item "yippee"}]}]
01:14TEttingerhooray
01:14TEttingerI was off a bit on merge, i should have thought of group
01:15TEttingerI was looking for a not-reduce solution because heavy uses of reduce tend to be harder to read
01:15jeayeWait, is that what he wanted?
01:15TEttinger(I'm not sure)
01:15jeayeWe have quite different outputs.
01:15TEttingerthey're similar enough that they could be changed to fit
01:16jeaye:)
01:16TEttingerI think the specific request was that it be a vector of maps
01:16jeayeYou may be more on point then.
01:16TEttingerI think a map where you could look up 2 to get all items where x was 2 would be nice
01:17jeayeI wonder if specter has something for this.
01:17TEttinger:D
01:21xrashTEttinger: thx, I will take a look on that too!
01:23huaweihi
01:25huaweii have a newbie question
01:40dysfunwell don't stick around long enough to ask it, will you?
01:41xrashjeaye: I see that you create the "grouped" map before actually constructing the final vector. Is the order of the "grouped" map keys guaranteed? I can test it and it seems to work, however can I trust it?
01:42dysfungroup-by will come out in order provided the collection was ordered
01:43jeayexrash: I'm using (fnil conj []) so the order is maintained.
01:43jeayeconj onto a vector pushes onto the end.
01:44jeayexrash: Naturally, you'd probably want a (let []) and not the (def grouped ...) that I had in the repl.
01:44xrashI'm still understanding that fnil thing, but I mean after the grouped map is created, when you apply the last `map` on it, is it guaranteed that it will traverse the "grouped" map in the order you have constructed it?
01:45xrashBecause maps may not maintian the key order.
01:45xrashDepending on implementation, I suppose.
01:45xrashYeah, I am already familiar with let.
01:45justin_smithyeah, in practice the shuffle happens after the 16 item threshold - usually
01:46jeayexrash: Oh, I see what you mean. You can use a sorted map or somethin'. At that point, I think the group-by approach may be nicer.
01:46jeayexrash: As for fnil, it takes a fn and some values and returns a fn. When you call that fn, any arguments which are nil are replaced with the values you gave up front.
01:47jeaye,(pr-str nil 5)
01:47clojurebot"nil 5"
01:48jeaye,((fnil pr-str 33) nil 5)
01:48clojurebot"33 5"
01:48jeayeThe order/place is kept though.
01:48xrashYeah, good explanation. (By the way, the description of reduce in clojuredocs.org is a beast :P)
01:48jeaye,((fnil pr-str 33 44 66) nil 5 nil)
01:48clojurebot"33 5 66"
01:48jeaye44 doesn't go in, since 5 is there in the second place.
01:49justin_smith,((fnil / 1 1) 2 nil) ; I didn't realize I could do this...
01:49clojurebot2
01:49justin_smithvery cool! thanks jeaye
01:49justin_smithI had only ever used fnil with one arg
01:50jeaye:)
01:53jeaye,((apply fnil pr-str (repeat 3 :unbound)) nil 5 nil)
01:53clojurebot":unbound 5 :unbound"
01:54jeayeIt's limited to 3 though, which is a bummer. Otherwise, you could use a lazy repeat and just have any nil arg be substituted.
02:06xrashjeaye: I think I understand your whole solution now, really kool, thanks!
02:07xrash,(mapv (fn [[k v]] {:x k :items v}) (group-by :x [{:x 2, :item "hooray"}, {:x 2, :item "yay"}, {:x 3, :item "yippee"}]))
02:07clojurebot[{:x 2, :items [{:x 2, :item "hooray"} {:x 2, :item "yay"}]} {:x 3, :items [{:x 3, :item "yippee"}]}]
02:07xrashNow this one seems to be a bit higher level, let me check it. :P
02:11xrashWell, group-by seems to magically do it all.
02:14TEttingeryay
02:15bdevel_(print "hello world")
02:16jeaye(no)
02:20TEttinger,(print "needs a comma at the start")
02:20clojurebotneeds a comma at the start
02:20justin_smithTEttinger: is there a clojurebot quine?
02:20TEttingerI think it ignores itself
02:21justin_smithbut is there an input that returns itself, complete with comma?
02:22jeayeNo, since the comma is just whitespace.
02:22justin_smithbut you can make the bot emit a comma surely - I know this must be possible, just speculated someone had one handy
02:24TEttinger,(print ",{}")
02:24clojurebot,{}
02:25TEttinger,",()"
02:25clojurebot",()"
02:26TEttingerdrat this will be a time waster
02:26jeayehaha
02:26justin_smithhaha, sniped
02:40ridcully_,(symbol ",(symbol \",\")")
02:40clojurebot,(symbol ",")
02:41ridcully_hmm
03:26osfameronTEttinger: ah, interesting. Don't think I care about leap-ahead/back (didn't know the concept even ;-) but will bear it in mind
03:26TEttingerheh, osfameron I just made use of it now that you brough it to mind
03:27dysfunthis sounds interesting, but i can't find the original exchange
03:27TEttingerI use it in a simple, not-professionally-secure method to obscure things like save files for games on phones
03:28TEttingerone thing I do is to shuffle the input string and apply some XOR to each character, up to the first 5 bits for reasons. this is totally reversible with jump-back or leap-back or whatever you can call it
03:29TEttingerthe length doesn't change, so the number of random bits produced is the same encoding and decoding
03:29osfamerondysfun: started with 01:44 <osfameron> can you generate repeatable random numbers?
03:29osfameronI'm UTC+1
03:29dysfunah
03:29TEttingerand it turns out there's some simple methods that pass randomness tests and perform well on the JVM
03:30TEttingerSplittableRandom is 3 lines, plus an update that you can control yourself
03:30dysfunwell any DRBG is repeatable given the same seed
03:30osfameronI'm actually not doing anything especially interesting with random numbers (was just thinking about implementing Candy Crush in clojure for lols)
03:30TEttingerexcept clojure doesn't allow seeds in rand-int and such
03:30osfameronand was disappointed that clojure rand doesn't have seeds, so would be impossible to do & test in FP stylee
03:31TEttingerit is kinda a strange omission, maybe related to using ThreadLocalRandom
03:31TEttingerwhich is also non-seed-able
03:31dysfunstill, you can use java's other random stuff
03:32osfameronyeah, that's fine and not too hard to wrap, but definitely an odd omission
03:32TEttingerindeed. java.util.Random, whatever SecureRandom is in, java.util.SplittableRandm on newer Java
03:32RovanionThe implementation of rand is simple, just copy it and add one argument: https://stackoverflow.com/questions/17445813/random-seed-math-random-in-java
03:33RovanionAnd replace Math.random with an instance of java.util.Random.
03:34TEttingeroh you mean to replace clojure.core/rand ?
03:34RovanionMake a new function rand'
03:34RovanionOr call it random.
03:35TEttingerjava.util.Random has some helpful tweaks above its LCG implementation type, but i don't know how the quality really is. it just discards a bunch of repetitive bits from a 64-bit random value
03:36TEttingerone bit it really is good that it discards it since I think it alternates 1, 0, 1, 0
03:38RovanionPerhaps I'm not understanding the issue correctly. But I thought we just wanted repeatable randomness for a game java.util.Random seems to be capable of it.
03:39RovanionEh, missed an 'and' there between game and java.util.Random.
03:42TEttingerRandom is capable of it yeah but I wouldn't rely on it just by default. it's very slow for what it does
03:43TEttingerSplittableRandom I consider an improvement all around
03:43osfameronI'll worry about that when I need the bare metal raw speed required for Candy Crush ;-)
03:44dysfunit only needs bare metal raw speed because it's hard work animating all those GIVE US YOUR MONEY screens
03:44osfamerondysfun: yeah, good point
03:44TEttingerbut the main thing you may want is the ability to get the current random state, for save files
03:45osfameronthey've got worse in the last 2 years (last time I got my android tablet out with CC installed it was much much less laggy)
03:45TEttingerRandom I don't think allows that
03:45osfameron(defn randfn ([] (randfn (java.util.Random.))) ([r] #(.nextDouble r)))
03:45osfameronis what I saw suggested
03:45osfameronyou pass it a seed and it generates a rand function
03:46osfameronwhich is mutating, but at least predictable
03:46TEttingerthat's not what that does?
03:46osfameronmight look at SplittableRandom though
03:46TEttingerI guess you could consider a Random object a seed
03:46TEttingerit may be serializable in some way
03:47osfameronyeah, you call e.g.: (def source2 (randfn (java.util.Random. 37)))
03:47TEttingeroh ok
03:47osfameronoh I see, yeah, it's a Random object which is the seed
03:47TEttingerthat's reasonable as long as there's a way to save the object seeds for later
03:48osfameronwell I only really need the seeds for testing
03:48TEttingercool
03:48TEttingerthen probably fine :D
04:08RovanionDoes anyone know why the spec macros like assert don't keep track of predicate names? I made a stupid little modification of assert to demonstrate: https://gist.github.com/Rovanion/10b5af393498500472c84cab53b1ff02
04:09dysfungoddamnit cognitect take this man's patch
04:10dysfunany other massive improvements you feel like making?
04:15RovanionPff, I don't think the word massive is necessarily appropriate here. Just a tiny little change which may be a bad idea because of X.
04:15dysfunwell i have spent rather a long time in the last week building stuff against the spec api and it's exhausting
04:15dysfunso to me, anything that makes spec explain itself better is a massive improvement
04:59TEttingercan't spell cognitect without tic con get
05:01dysfungit tec con
06:32warrshrikehey
06:33dysfunhello
06:33warrshrikesomeone suggested a good windows jdk thing once
06:33warrshrikei forgot the name
06:33dysfunzulu?
06:33warrshrikedysfun: hey man how you been
06:33warrshrikedysfun: yup thats it
06:33dysfunyeah not bad and you?
06:34warrshrikedysfun: same old same old. lifes better now that i dont have to fight js-cljs interop constantly ~~ working on jdk clojure now
06:35dysfunyeah me too. turns out the jvm is much more fun than js
06:35lxsameeris zulu e jdk ?
06:35lxsameers/e/a/
06:36dysfunyes
06:36warrshrikedysfun: Amen to that brother
06:36dysfuni'm also doing kotlin
06:36dysfunbut at the minute most of the libraries for kotlin are java ones
06:37dysfunso i'm using clojure and kotlin together
06:37warrshrikeEverything works much more 'organically' in jdk
06:37warrshrikeyeah kotlins cool
06:38warrshrikebut any particular reason for using it with clj?
06:38warrshrikecouldnt you do clojure only?
06:38dysfuni could, but i'm not doing
06:38dysfunshocking i know, but there are places where a type system is useful
06:39lxsameerdysfun: what's the difference between zulu and openjdk ?
06:39lxsameerjs sucks by the way
06:40dysfunzulu is polished up and engineered to pass the JCK. those patches will eventually go back into openjdk, but at any given point in time, openjdk isn't guaranteed to pass the conformance test suite
06:40dysfunso essentially it's the less mystery meat version of openjdk
06:40lxsameerdysfun: ow, good to know
06:45warrshrikedysfun: yeah makes sense. static typing improves tooling immeasurebly
06:46warrshrikekotlin comes off as a more portable and platform independent Swift
06:46dysfunyeah, there are swift influences
06:46dysfunalso c# influences. c# is quite a better language than it used to be
06:46osfabibisic# looks mildly interesting
06:47osfabibisiI keep meaning to play with linq, but not enough to suffer working on windows
06:47warrshrikedysfun: haven't ever used c sharp...but i always thought it was java-ey
06:47warrshrikejava itself has improved much btw
06:47osfabibisidysfun: so you're doing the core components in kotlin and stitching them together in clojure ?
06:48dysfunsomething like that, yes
06:49dysfunall the business logic is written in clojure and the high performance parts are written in kotlin mostly, but that's because i haven't gotten as far as the problems where types really help out
06:50dysfunoh also the bits where clojure gets really fugly are written in kotlin
06:50dysfunsome things are just easier to express in a java-like language
07:07Hanonimdysfun: how has been your experience with zulu ? you've been using it for a while i believe
07:08dysfunit works as described, what can i say?
07:09Hanonimnothing weird to declare
07:09dysfunoh weirdnesses of course, but nothing i can pin down to being its fault
07:10Hanonimrelative to oracle ?
07:10Hanonim:q
07:10dysfunthe purpose of the JCK is prove it works
07:10dysfunboth have been subjected to it
07:10dysfunthere should be no difference from a user perspective
07:19ridcully_i have recently replaced an oracle jdk with zulu in production -- nothing odd there
07:20Hanonimthey make money only out of consultancy ?
07:21ridcully_dont they also have their own jdk (or fork) for some border cases?
07:26dysfunthey make money primarily off consultancy and their zing jvm which will basically get you low pause time garbage collection for free and a bunch of other things
07:26dysfunthey also produce (produced?) some coprocessors for java garbage collection
07:26Hanonimwow, i've never even heard about such coprocessors
07:27dysfunoh and they've been doing an IOT java build as well
07:27Hanonimyes i've been experimenting with it on the rpi but not enough to have a firm opinion
07:28Hanonimbut it looked like it was behaving almost as fast as the oracle jvm optimized for arm, that looked promising
07:29dysfunoohj
07:29Hanonimanyway i'll use it in production quite soon
07:30dysfunis this the free one or the paid one?
07:30Hanonimfree
07:30dysfuncool
07:30Hanonimopenjdk isn't optimized at all for arm, it is about 10x slower than oracle
07:30Hanonimand oracle... well, you know...
07:31dysfunhttps://www.azul.com/products/zing/falcon-jit-compiler/ # fascinating. i followed the open source project do this year for a while
07:31dysfuns/year/
07:33Hanonimis it mostly for perf ? or does it add something new ?
07:33dysfunjust perf
07:34dysfunbut add it to pauseless GC and eliminating the warmup phase when restarting and it starts to look quite compelling
07:35Hanonimzing does look compelling, yes
07:36dysfuni don't fanboi for proprietary software, but if it were open source...
07:38Hanonimi wonder how much better is their GC in real life
07:41dysfunthe first step is identifying that you have a GC problem, otherwise it's pointless
08:10warrshrikedysfun: what gets really fugly in clojure?
08:15dysfunanything involving abstract things for a start
08:18Hanonimthat's broad
09:20Hanonimis there an obvious way to add metadata to the symbol rather than the value (def sym x) ?
09:20Hanonimbesides alter-meta
09:21dorianhey random question: is there any way to start a cider repl without being in the context of a project?
09:27ragepandadorian: cider-jack-in doesn't work?
09:27dorianpretty sure it complains about not being situated in a project
09:27dorianone sec, checking
09:28dorianoh, weird, there it is
09:28ragepandait worked?
09:28dorianyeah, but in my head i tried that before
09:28dorianand it was like wah wah where's the lein project
09:29ragepandathat's weird. are you sure you're not in a project right now?
09:29dorianyep
09:30dorianmaybe i'm misremembering something or had triggered some weird behaviour before and it just stuck in my memory
09:30ragepandahttps://cider.readthedocs.io/en/latest/up_and_running/#launch-an-nrepl-server-and-client-from-emacs
09:30ragepandadoesn't mention it running without a project, let me try it on my machine
09:31ragepandaah, it prompts you. "Are you sure you want to run a Clojure REPL without a project?"
09:31dorianha okay that's funny because it was totally silent when i just tried it
09:32dorianweeeeird
09:32dorian0.13.0snapshot
09:32dorianassuming that's not the newest
09:34ragepanda0.15.0snapshot for me
09:37RovanionI like the ragepanda moniker.
09:37ragepandemicrage against the pandas
11:57osfabibisiwe quite often have threading macros with this sort of thing in them: (#(assoc % :key (message-key (:value %))))
11:57osfabibisiis there a nicer way to do this?
11:58osfabibisie.g. we want to assoc a key to the threaded hash-map, based on a value in the entire hash-map
11:58osfabibisie.g. it's not the same as an update, which assoc's a key based on the value of *that* key
11:58justin_smithosfabibisi: there's as->
11:58osfabibisiah yes, lemme have a look at how to use that
11:59justin_smith(as-> some-hashmap m (assoc m :key (:value m)))
11:59justin_smithit pays of more with more clauses, but even that is nicer than the #() version imho
12:00justin_smiththough as-> is just a shorthand for a let block that always uses the same binding symbol in every clause
12:00justin_smith(it's helpful to read the macro source)
12:00osfabibisiyeah, it's not all that nice really
12:00osfabibisiyou could think of it as: (as-> % (assoc % :foo (:bar %))) ;-)
12:01osfabibisibut I guess there's not much you can do about that
12:01justin_smithexcept we get to use a more meaningful symbol, and multiple clauses
12:02justin_smithand you were mentioning threading - you can put as-> inside ->, it's designed for that
12:02justin_smith(-> foo (frob) (as-> the-foo (assoc the-foo :x (:y the-foo))))
12:03osfabibisiyes indeed
12:04osfabibisiI wonder if I want to write a macro that would let me write that as: (-> m (assoc-by :foo :bar)) though
12:04justin_smithit's close to being clojure.set/rename-keys...
12:05justin_smiththough that doesn't match your original example
12:05osfabibisisorry, the :bar there is a function
12:06osfabibisirather than a key name. sorry, I'm mixing my examples
12:07justin_smithI'm also fond of the plain-old procedural let block
12:07osfabibisisure
12:07osfabibisiin fact the answer might just be: (-> m (some-func-that-encapsulates-that-awkward-thing-I-was-whining-about))
12:08justin_smiththis may even be one of the rare uses of letfn... ?
17:39{blake}How does cljsbuild determine what to compile? I've had this project for over a year, and now it's ignoring everything but my "main" cljs.
17:45{blake}It detects when I make a change to a non-main file, and that triggers the recompile but never seems to compile it.