#clojure logs

2015-09-19

04:34Empperi01:54 [rajaniemi] DCC SEND from crowgoose [37.187.79.138 port 43352]: virus.exe [13kB bytes] requested in channel #clojure
04:34Empperi01:59 [rajaniemi] DCC aborted receiving file virus.exe from crowgoose
04:34Empperiokey dokey
04:35Empperigot to say one has to be pretty desparate to try that on such a channel
04:55ahoegh_Empperi: crowgoose tried the same one me.
05:24m1dnight_Does anyone know how I can create .edn config files that can change after I created an uberjar? As it currently stands I have to recreate the uberjar each time I change the config.
05:31mavbozom1dnight_, what's this config.edn file contains? can't you put the config.edn file somewhere outside the uberjar?
05:33m1dnight_Well, the thing I don't know exactly is, can I just put a relative path in the codebase then? So that, say, the foo.edn file is always in the root directory of the jar file?
05:34m1dnight_Maybe I can just play around with it. (edn/read-string (slurp (io/resource "servers.edn"))) This is how I read the config file at the moment.
05:36mavbozoyou can run your uberjar with java -jar -Dconfig.location="/etc/my-app-config.edn"
05:36mavbozoand in your code, you can get the config.location with (System/getProperty "config.location")
05:37TEttingerm1dnight_: if it's a resource it's inside the jar. you can modify the jar to replace the resource I think
05:37m1dnight_oh that might be something Im interested in, mavbozo
05:37m1dnight_TEttinger: but the thing is that modifying/recompiling the jar takes some time and I would just like to stop and start it to re-read the config
05:37m1dnight_It doesnt have to be inside the jar.
05:37m1dnight_I will have a look at it right away!
05:37TEttingeror you can change it from a resource to just (edn/read-string (slurp "servers.edn"))
05:38TEttingerhm
05:38TEttingerif you had a resource called servers.edn and you tried to get a local file with the same name, it would prefer the resource I think?
05:38TEttingernot sure
05:39m1dnight_To the experimentation-mobile!
06:12justin_smithyou need io/resource to get the resource inside the jar
06:12justin_smiththen it finds the first one in the classpath
06:25m1dnight_I stranded on setting the system property and then reading in the files like this: (edn/read-string (slurp (io/file config-path file)))
06:25m1dnight_where config-path is the System/getProperty and file is the filename.
06:26justin_smithif you don't need to read anything inside the jar, that would work
06:27m1dnight_Exactly! If I want to change the path to a temporary database or w/e I dont have to recompile. Which is nice.
07:03trissthere's not a function like swap! that returns the value before the function provided is applied is there?
07:11m1dnight_Afaik there is not, no.
07:12Bronsatriss: no, http://dev.clojure.org/jira/browse/CLJ-1454
07:13m1dnight_Does anyone know if its possible to fold with an index? I want to iterate over a list of integers and return the index (1-based) of the higherst value.
07:14trissokeydoke. keep a ref to previous value isn't too much hassle for now.... surprised how many times its been implemented tho
07:15m1dnight_Are refs not an option for the value as well?
07:15m1dnight_You could use (dosync (ensure x) (let [old-value @x] (ref-set! x new-value)))
07:15m1dnight_or somethiong
07:16m1dnight_You could use (dosync (let [old-value (ensure x)] (ref-set! x new-value))) even!
07:17Bronsam1dnight_: using the STM for simple CAS semantics seems an overkill
07:17m1dnight_Well you can then store {:curr :old} in the atom and update the old in swap! function and read that out afterwards
07:17Bronsam1dnight_: wrt your question, just use a tuple as acc value to your reducing function and keep track of the ids
07:18Bronsaand incur a map lookup everytime you need to access the value?
07:18m1dnight_and that would work in a concurrency setting as well as you get the new value returned and can read the "old" value from the result of swap
07:19m1dnight_a map lookup is about O(1).
07:19m1dnight_*about*
07:20Bronsam1dnight_: that's irrelevant, it's always a c more than no lookup & forces you to (comp :new-value deref) rather than simply deref every-time you need to get the value
07:21m1dnight_Thats true. But the point is that you have to work with swap! and that it can not do what triss wants so you have to work around that.
07:21m1dnight_How would you do it?
07:22Bronsam1dnight_: sure but there are better workarounds than the one you proposed, see http://dev.clojure.org/jira/browse/CLJ-1454
07:22Bronsahttps://github.com/flatland/useful/blob/develop/src/flatland/useful/state.clj#L43 this one solution I like the most
07:22m1dnight_oh I see. yes the compare and swap one is much better idd
07:23m1dnight_Allright Bronsa, I stand corrected! :)
07:23trisscheers Bronsa
07:23trissand m1dnight_ !
08:12gkoIf I want to create a parser library with a default "main", should I use lein new app (that can be 'require'd to be used as any other library) or lein new default (and add "main" stuff myself) ?
08:52trissis it possible to make fireplace put evaluations output in to a vim buffer so I can refer back to it?
08:52trissi'd love to have a pane open with the output of the last few commands in.
09:02trissoh it seems :Last is doing the job
10:54monstaWhat is the differenct from using (vec (1 2 3)) and (into [] (1 2 3))
10:57lodin_monsta: I don't know, but I always use vec if what I want to do is to "cast" a sequence to a vector.
11:27kavkazWhat is the most preferrable SQL library for Clojure? Is there one that most people use for backend stuff?
11:35justin_smithkavkaz: clojure.java.jdbc is probably the most used
12:21xtrntrcan i interrupt a doseq?
12:22tcrayford____xtrntr: you can throw an exception to interrupt I guess :/
12:23tcrayford____there's no `break` keyword or anything else like that in clojure though
12:23xtrntralright
12:23xtrntrthanks
12:24tcrayford____generally you'd just use `filter` to remove the elems you don't want to iterate over though
12:26xtrntrno, there's some kind of animation loop.. i suppose if i wanted to kill the animation halfway, i should put some kind of flag in the function?
12:26xtrntror is that bad clojure?
12:29noncomxtrntr: user (loop) with (recur) then
12:29tcrayford____yeah, I'd vote for loop/recur
12:30xtrntroh, there's a company named such
12:30xtrntr:)
12:37justin_smithxtrntr: if your processing of a sequence needs to stop arbitrarily, use reduce and reduced
12:37justin_smithuse loop if you are doing something more complex than just walking along a sequence
12:38justin_smith,(reduce (fn [acc el] (if (> el 10) (reduced acc) (conj acc el))) [] (range))
12:38clojurebot[0 1 2 3 4 ...]
12:38justin_smithanyway, range is infinite, that's our proof the reduce stopped
12:38justin_smith*indefinite
12:39justin_smith,(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (conj acc el))) [] (range))
12:39clojurebot[0 1 2]
12:39justin_smith,(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (conj acc el))) [] (range))
12:39clojurebot[0]
12:39justin_smith,(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (conj acc el))) [] (range))
12:39clojurebot[]
12:39justin_smith,(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (conj acc el))) [] (range))
12:39clojurebot[]
12:39xtrntri'm going to need time to get used to this..
13:01noncomhow do i convert between js Date and cljs-time date ?
14:00tolstoySomething like: (cljs-time.coerce/from-long (.getTime (js/Date.))) ?
14:00m1dnight_Cljtime uses a lot of different formats
14:00justin_smith,(frequencies (repeatedly 1000 #(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (+ acc el))) 0 (range))))
14:01clojurebot{0 754, 1 129, 15 8, 21 4, 36 3, ...}
14:01tolstoyOh, from-date. ;)
14:02justin_smith,(str (frequencies (repeatedly 1000000 #(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (+ acc el))) 0 (range)))))
14:02clojurebot"{0 749935, 153 2, 1 125070, 55 219, 15 7802, ...}"
14:03m1dnight_justin_smith: i was just looking for the frequencies today. Damn.
14:03justin_smith,(apply str (frequencies (repeatedly 1000000 #(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (+ acc el))) 0 (range)))))
14:03clojurebot"[0 750190][153 2][1 124774][55 247][15 7791][21 3912][136 3][91 28][36 995][6 31478][28 1906][3 62449][66 120][45 496][78 73][120 7][10 15513][105 15][190 1]"
14:04justin_smith,(apply str (sort-by second (frequencies (repeatedly 1000000 #(reduce (fn [acc el] (if (> (rand) 0.5) (reduced acc) (+ acc el))) 0 (range))))))
14:04clojurebot"[171 1][190 1][153 2][136 5][120 10][105 10][91 32][78 64][66 112][55 238][45 492][36 976][28 1965][21 3914][15 7745][10 15816][6 31466][3 62785][1 124896][0 749470]"
14:20csd_what's the simplest way to replicate common lisp's progv in clojure? http://clhs.lisp.se/Body/s_progv.htm -- i.e. where you pass it a map and it sets up let bindings for all the k-v pairs in the map
14:21justin_smithcsd_: flatland/useful has a macro that does that
14:23csd_any idea what it might be named?
14:24justin_smithone moment
14:27justin_smithcsd_: I either lost it or misremembered
14:27justin_smithcsd_: it would require calling eval unless the hash-map is a compile time literal
14:29csd_nah the bindings need to be made dynamically
14:29justin_smithcsd_: the problem is you don't even know what keys (therefore what symbols) might be bound
14:29justin_smiththat requires eval
14:29justin_smithunless you have a list of possible symbols somewhere...
14:31csd_i'm trying to port this over from CL http://norvig.com/paip/patmatch.lisp
14:32csd_i think i'd know the all the key-side symbols of the let, but not the value-side
14:32justin_smithI guess you could implement your own ad-hoc binding / resolution mechanism that does not use clojure eval
14:32justin_smithbut it won't be proper local bindings either
14:33csd_this sounds outside my depths
14:33justin_smithoh, wait, if you know all the possible left-hand-sides this might be a case for with-local-vars
14:33justin_smith(doc with-local-vars)
14:33clojurebot"([name-vals-vec & body]); varbinding=> symbol init-expr Executes the exprs in a context in which the symbols are bound to vars with per-thread bindings to the init-exprs. The symbols refer to the var objects themselves, and must be accessed with var-get and var-set"
14:34justin_smithoh no, never mind
14:34justin_smithcsd_: couldn't you convert that code to use a hash map and do explicit hash-map lookups to get the values?
14:36csd_i guess, although not sure how off hand
14:39csd_seems doable i suppose
15:12amalloyjustin_smith: that's certainly not in useful. the closest thing to that i've done is write an answer on stackoverflow saying it's a bad idea
15:34justin_smithamalloy: on the surface level, I was factually wrong, on a more real level, I was correct that you had the right answer
15:34amalloyhaha
15:34amalloyvery deep indeed
15:36gfredericks~this is not a case for with-local-vars
15:36clojurebotAck. Ack.
15:37mungojellyi don't really understand how these leiningen dependencies work i guess i need to read something about it, does it actually look at these urls to find the dependency or what is it looking in
15:37mungojellyhow do i say a dependency on flatland/useful, like how do i know which version to say? :/
15:37justin_smithmungojelly: it searches your repositories
15:37justin_smithit starts with like maven central and clojars and maybe sonatype
15:38mungojellyoh ok it just seemed to magically know everything in the universe
15:38justin_smithhaha
15:39mungojellyso is what i should do search on maven/clojars myself to find what versions i might want to tell it to depend on?
15:39justin_smiththere's a default config that sets up the first repositories for you (but it is possible to replace it)
15:39justin_smithmungojelly: if you are not sure what version to get, sure. Sometimes I just look at the version tag / readme on github too.
15:40justin_smithmungojelly: there is also "lein search" which takes a long time to build the index though...
15:40justin_smithmungojelly: another interesting thing to check is http://crossclj.info which shows who is using what version of what library (in open source at least)
15:41mungojellythat's what i had been doing was entering the lein dependencies line it tells you to on github readmes but when things didn't tell me what to say i discovered i didn't know how that magic worked
15:43mungojellysomeone linked to crossclj.info and it was too interesting for me to have the bandwidth to understand it, that's so much information
16:03noncomwhat's the best way to get the 2 dates representing the beginning and the end of the current month?
16:05gfrederickswith clj-time?
16:06justin_smithgfredericks: is there a reason not to use Calendar?
16:07gfredericksI don't know, I was just trying to figure out the background for the question
16:08justin_smithI mean I've only used the API a little, but I never see people recommending using it, and wonder why
16:10Inteyjsutin_smith: Calendar is native and correspond to clojure.instant ?
16:11justin_smithIntey: the instant reader in clojure is java.util.Date, but things like "date for first and last days of a month" would be done with the Calendar api and not the Date api
16:11justin_smithand maybe that unintuitive split is part of why nobody likes those apis...
16:12InteyIn clj-time, i see 3 funcs, for noncom question: now, start, end. I don't know, but with those can be done.
16:13noncomah, sorry, yes, in clj-time (cljs-time to be precise, but there is not much difference)
16:13noncomin the emantime, i found the way - i take (now), make a new date with year and month - that's the start and then make the end with +1 month
16:14justin_smith,java.util.Calendar/UNDECEMBER ; 13th month of the year
16:14clojurebot#error {\n :cause "Unable to find static field: UNDECEMBER in class java.util.Calendar"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to find static field: UNDECEMBER in class java.util.Calendar, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message ...
16:14noncomahhaha :D
16:14noncom13th monh
16:14noncomjava can do this
16:14justin_smith,java.util.Calendar/UNDECIMBER ; 13th month of the year
16:14clojurebot12
16:14justin_smithhaha, spelled it wrong the first time
16:14noncomis it an easter egg?
16:14justin_smithno, it's a documented part of the api
16:15noncom:/
16:15noncom:D
16:15justin_smith,java.util.Calendar/WEDNESDAY
16:15clojurebot4
16:16justin_smith,java.util.Calendar/HOUR
16:16clojurebot10
16:16justin_smithOK, this is a weird API
16:16noncomreally :)
16:18justin_smithnoncom: OK, undecimber is there because localized calendars are supported, and the Hebrew calendar, among others, there is sometimes a 13th month
16:18noncomthis makes sence
16:19noncombut the name is funny nevertheless :)
16:19justin_smithit is a weird name
16:19justin_smithhttps://en.wikipedia.org/wiki/Undecimber
16:19justin_smithbut it's real
16:20noncomhuh, so all this is serious..
16:20noncomgood to know
16:21justin_smithit's justin_smith 's rule of locales: anything localized will support things you find hilarious
16:22justin_smith(see also unicode snowman)
17:46raryOkay, I've switched to idea+cursive. It is really nice, I like it!
17:46raryjustin_smith: thank you for your advice again.
17:47raryrainbow parentheses are beautiful :)
17:51raryI am reading the Joy of Clojure now and authors write that if there would be a strong request to publisher, they will write a separate book about Clojure compiler implementation details
17:52raryLets create a strong request, ha? :-) it will be definitely interesting reading.
18:47obliviasimplexhey, I seem to be having some trouble with Cider. M-x cider-jack-in gives me these errors and stack traces: https://bpaste.net/show/fcd37a267ba5
18:48obliviasimplexAnyone know what the trouble is here, and how to fix it?
18:57domokatois it possible to get the value of a var of a symbol passed into a macro? or does the value not exist yet?
19:00domokatothis is in a namespace file to be compiled, not the repl
19:01amalloydomokato: you can do it, but it's more often a bad idea than a good one. what is the big picture?
19:05domokatomaybe i'm trying to do something dumb, but I'm trying to write a macro that allows me to inherit fields between records. I don't intend to ever use the base record, so I've just defined it as a vector of symbols of fields and I'm trying to pass it into the macro, which would expand it into a call to defrecord
19:08domokatoalong with the additional fields
19:09amalloyinheriting fields between multiple records sounds like a bad way to get composite data. if you have N records which all need fields x,y,z, why not (defrecord Q [x y z]) and then just give those N records a single q field?
19:13domokatoin my model, it just seems like a is-a relationship rather than a has-a
19:13justin_smithdomokato: clojure really doesn't do is-a (at least not concretely)
19:13domokatoalright, i'll just go with the has-a then :)
19:13domokatothx
19:14justin_smithit does is-a for interfaces (is-a thing that you can run this function on) but not data (no is-a thing that has these fields)
19:15domokatoyeah, that's why i was trying to implement it, but seems to not be worth the effort
19:16domokatoi guess it's a little bit annoying to do it the has-a way because I have to instantiate the inner record manually in every case
19:16domokatomaybe it's okay...
19:17justin_smithdomokato: using prismatic/schema you can do "has these fields" as an insertion, and using clojure.core/merge you can "inherit" it
19:17justin_smiths/insertion/assertion
19:21domokatoi can't find any insertion
19:24justin_smithdomokato: see my correction - I meant assertion
19:25justin_smithalso, off topic but wow, I found a URL that can't be resolved, but if you paste it into chrome's browser bar it crashes the entire browser (not just one tab, the whole browser)
19:27domokatohm...don't see assertion either :(
19:27domokatohttps://github.com/Prismatic/schema ?
19:27domokatoor do you just mean...do an assert?
19:27justin_smithyes, you can use s/defn for example to make a defn which asserts certain keys are present in some arg
19:28justin_smithdomokato: sorry, I am talking about s/validate (and the other things which use that)
19:29domokatosorry, i'm unfamiliar with this library
19:31domokatoyeah, i'm trying to use merge but i still have the issue of getting the value of a var from its symbol
19:32justin_smithin a macro?
19:32domokatoyeah
19:32justin_smithin a macro, getting the symbol means too many layers of quoting
19:32justin_smithso if you are using ` you need ~ somewhere
19:33domokatoi have a var like (def body-state ['sprite 'sprite-info]) and i'm passing body-state into the macro call, but when i unquote the the value passed in i get a var, i believe, not the actual vector
19:36justin_smith,(= ['sprite 'sprite-info] '[sprite sprite-info]) ; btw
19:36clojurebottrue
19:36domokatoah
19:37domokatoyeah, i noticed that
19:37domokatoanyway, here's my macro right now: (defmacro pseudo-extend [name parent fields & remainder] `(defrecord ~name ~(apply merge parent fields) ~@remainder))
19:37domokatoit works when passing in a vector literal, but not when passing in a vector var
19:38justin_smith,(apply merge [:a :b :c] [:d :e :f])
19:38clojurebot[:a :b :c :d :e ...]
19:38justin_smithweird
19:38justin_smith,(into [:a :b :c] [:d :e :f]) ; this is the normal way to do that
19:38clojurebot[:a :b :c :d :e ...]
19:40domokatooh okay nice
19:41justin_smith,(let [name 'n parent '[a b c] fields '[d e f]] `(defrecord ~name ~(into parent fields)))
19:41clojurebot(clojure.core/defrecord n [a b c d e ...])
19:41justin_smiththat looks legit (if your args are of the types you think...)
19:42justin_smithbut what I meant by using merge was not defining a record that has the merged field vectors, but using a map (or record) and using merge to get the default field key / values for things that you don't explicitly override in the hash-map
19:43justin_smithsince defrecord is already using a hash-map like thing instead of an object, why not use hash-map merge to get default key / value pairs
19:44domokatoi think your implementation that worked above isn't quite analogous to using defmacro
19:45domokatoi just got it to work using: (defmacro pseudo-extend [name parent fields & remainder] `(defrecord ~name ~(into @(resolve parent) fields) ~@remainder))
19:47justin_smithdomokato: that's a fair bit of work to do something records allowed already (you can merge an instance of a defrecord class with a normal hash-map)
19:49domokatoright but i'm trying to inherit fields from another record. Not their values, just their declarations. I will use merge with normal hash-maps later to instantiate those fields
19:50justin_smithwhat good does inheriting declared fields do when defrecord allows associating any field you want to a record instance?
19:50justin_smith,(defrecord Foo [bar baz])
19:50clojurebotsandbox.Foo
19:50justin_smith,(assoc (->Foo 1 2) :quux 42)
19:50clojurebot#sandbox.Foo{:bar 1, :baz 2, :quux 42}
19:50rhg135performance if there's many instances with the extended fields
19:51domokatoyeah, performance
19:51rhg135you did profile this right?
19:51domokatoyeah
19:51domokatoit's slowing down my draw loop considerably
19:51domokatokeyword lookups in hash maps
19:52domokatothat's why i'm changing everything over to use records instead of maps
19:53rhg135something about this feels wrong, but I can't think of anything better
19:53domokatotell me about it
19:53domokato:)
19:53justin_smithdomokato: why not make those fields the render loop needs be the record fields, and associate other records into it (not just their fields)
19:57domokatoif I have a bunch of records with BodyState as a field, every time I instantiate one of those I need to do (map->Thingy {:body-state (map->BodyState ...) ...}) rather than just (map->Thingy ...)
20:00domokatoin my case i generally do (map->Thingy nil) first then merge in the data later
20:00justin_smithdomokato: when you do that, you don't get any of the perf benefit
20:01justin_smith,(type (assoc (->Foo nil) :a 1 :b 2))
20:01clojurebot#error {\n :cause "Unable to resolve symbol: ->Foo in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: ->Foo in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: ->Foo in this...
20:01justin_smith,(defrecord Foo [bar baz])
20:01clojurebotsandbox.Foo
20:01justin_smith,(type (assoc (->Foo nil) :bar 1 :baz 2))
20:01clojurebot#error {\n :cause "Wrong number of args (1) passed to: sandbox/eval49/->Foo--64"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: sandbox/eval49/->Foo--64"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [sandbox$eval91 invokeStatic "NO_SOURCE_...
20:01justin_smithoops
20:01justin_smith,(type (assoc (map->Foo nil) :bar 1 :baz 2))
20:01clojurebotsandbox.Foo
20:01justin_smithoh, wait...
20:02justin_smithnever mind, that only happens with dissoc
20:02domokatowhat does?
20:02amalloywell, it's still true you don't get much benefit if you're building records out of maps
20:02justin_smith,(type (assoc (dissoc (map->Foo nil) :bar) :bar 1 :baz 2))
20:02clojurebotclojure.lang.PersistentArrayMap
20:02justin_smiththe dissoc makes it not be a record instance, even if you attach the field later
20:03domokatoah, good to know
20:03amalloyif you are using records for performance, which is rare but not unheard of, you should probably call the constructor yourself, or at least the ->Foo constructor rather than map->Foo
20:03domokatoit's the access i'm worried about, not so much the instantation
20:06domokatothe field accesses happen in the draw loop every frame. the instantiation happens at the beginning of the game or just once every few frames
20:07justin_smithdomokato: another option to consider is ECS where instead of iterating over objects and accessing fields, you can directly iterate the fields
20:11justin_smithdomokato: or a protocol, where you provide the data / functionality via protocol functions rather than via direct field access
20:12phaseNiis (swap! blah (fn [x] nil)) the same as (reset! blah nil)?
20:12rhg135how is polymorphic method dispatch faster than field access?
20:12rhg135in theory, yes, phaseNi
20:13rhg135semantically, rather
20:13justin_smithphaseNi: not quite, swap! retries if there is concurrent modification, reset! does not
20:14justin_smithrhg135: now I wonder, maybe it's not faster than hash lookup, that's a good point
20:15phaseNijustin_smith: Out of curiosity, in this case, would it really matter?
20:15domokatojustin_smith: thanks, and everyone else too :)
20:15phaseNijustin_smith: it just changes the timing a bit
20:15rhg135you can't now if it'll matter
20:15justin_smithphaseNi: not just timing, also the resulting value if there is concurrent modification
20:15rhg135not without the rest of the things touching it
20:16mungojellycache what the painter needs and make updates to that only as there are changes in the model
20:16phaseNijustin_smith: i mean if the other thread happened slightly slower the value would still be changed
20:16phaseNis/slower/later/
20:16justin_smithphaseNi: if the other thread did a reset! this is not true
20:17rhg135~mutable state
20:17clojurebotmutable state is bad
20:17phaseNiheh
20:17rhg135it becomes dependant on the order of thiings
20:18amalloyjustin_smith: i don't think you can ever tell (reset! a x) and (swap! a (constantly x)) apart, if no concurrent swap! function has side effects (other than the swap of course)
20:18phaseNiyes, what amalloy said is what i was thinking
20:20justin_smithhmm
20:27justin_smithrhg135: in my criterium test, polymorphic method access is much faster than defrecord field access, trying the tests again with type hints (tried unhinted first) and will paste the results
20:28justin_smithand hinted field access is pretty much identical to unhinted polymorphic method via defprotocol
20:29rhg135that is strange
20:29rhg135way to go jit
20:30amalloyhinting doesn't matter to protocols at all
20:30justin_smithand when hinted, the protocol method call is unchanged (uploading to refpheap now)
20:30justin_smithamalloy: haha, so I discovered
20:31justin_smithhttps://www.refheap.com/109749
20:32justin_smithrhg135: domokato: so, turns out where JIT applies, a protocol method is as good as field access on a record, and you can do composition of protocols much more cleanly than composition / "inheritance" of base record fields
20:33rhg135that is very strange
20:33rhg135I love the jvm
20:33amalloyjustin_smith: fwiw the jit isn't the only thing optimizing those protocol method calls. if you had the same line of code dispatching to two different implementations in alternation, the inline cache would never hit
20:34justin_smithhmm, OK
20:34amalloyoh, and it makes a big difference whether the record implements the protocol inilne or was extended to it
20:34justin_smithoh yes, that is definitely true, I knew that one
20:35rhg135is the cache that big a factor?
20:37amalloyprobably. avoids map lookup and hierarchy dispatch i would think
20:45rhg135it seems not to for me
20:49justin_smithrhg135: seems not to?
20:50rhg135https://www.refheap.com/109750
20:51rhg135not a huge difference per 100 iterations where one is a cycle of two types and the other is of one type
20:55domokatomy records store changing state and are kept in atoms, so i don't think protocols would work here?