#clojure log - Jan 16 2016

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:23 retrogradeorbit: hey. I need some opinions on style

0:23 TimMc: You've come to the right place.

0:24 retrogradeorbit: where is the line between threading macro and just nesting?

0:24 https://github.com/retrogradeorbit/geoip/commit/3e79e5adb2384121017ab1aee98136d04af64d8c

0:24 whats better?

0:24 stylistically... before the commit? or after?

0:26 justin_smith: retrogradeorbit: why do you use ->> twice on lines 35 and 36 instead of using one ->> starting on line 34?

0:26 (->> d-map (keys) (filter ...) (reduce ...))

0:27 retrogradeorbit: justin_smith: nice. yes!

0:28 justin_smith: retrogradeorbit: similarly on line 26, instead of ->> inside ->, you could just use ->>

0:28 retrogradeorbit: of course, cause they're all single arity

0:28 justin_smith: (->> d-map (keys) (sort) (take-while ...) (last) (d-map))

0:31 retrogradeorbit: so when do you thread, and when do you nest?

0:31 is there some thinking around this?

0:31 or is it just do what you want?

0:31 justin_smith: I nest when it's less than four calls deep, usually - more than three and threading is usually clearer.

0:32 but I think this is a preference thing, some prefer never to use threading

0:32 sometimes let bindings are simpler than threading also

0:42 TimMc: retrogradeorbit: Also see as->, which expands the number of situations in which threading can be used.

0:47 slim_: list

3:48 sztamas: hi, is http://dev.clojure.org/jira/secure/Dashboard.jspa the current JIRA page for Clojure? It seems to be unresponsive ATM

3:51 hiredman: works for me

3:53 sztamas: yes, loaded for me now as well

3:53 thanks for checking

3:56 very slow though

4:35 favetelinguis: how can i jump to the source of the error in emacs cider from the error buffer?

5:11 WickedShell: can you type hint the content of a delay'd var? IE I always know that when I deref it I will be looking at a object Foo, and currently for interopt reasons I have to hint every location where I deref the var

5:47 amalloy: no. but you can write a function that derefs the var, and hint that function

5:49 TEttinger: a ha!

5:51 ,(defn ^_^ ^String [a] @a)

5:51 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Metadata must be Symbol,Keyword,String or Map>

5:51 TEttinger: aw

5:52 ,(defn -_- ^String [a] @a)

5:52 clojurebot: #'sandbox/-_-

5:52 TEttinger: ,(def at (atom "hey"))

5:52 clojurebot: #'sandbox/at

5:52 TEttinger: ,(-_- at)

5:52 clojurebot: "hey"

5:53 lokien: TEttinger, whaat are you doing here?

5:58 TEttinger: testing what amalloy said

5:59 I wonder when gfredericks will awaken

5:59 lokien: too bad irc doesn't show history

5:59 TEttinger: gfredericks did some neat work regarding splittable immutable PRNGs

6:00 benchmarking over here seems to show that the core of SplittableRandom, which is the SplitMix64 algorithm, is really really good on the JVM

6:02 lokien: splittable immutable prngs - what does "splittable" mean?

6:03 "Splittable

6:03 PRNG

6:03 s,

6:03 in contrast to linear

6:03 PRNG

6:03 s, allow the creation of two (seemingly)

6:03 WickedShell: amalloy, valid approach. I really need to learn how to write clojure macro's apparently :/

6:03 lokien: independent generators from a given random number generator"?

6:03 oh man sorry

6:03 I won't ctrl+v into irc ever again

6:05 TEttinger: 1,269,975,332 nanoseconds to generate 1,000,000,000 numbers

6:05 that's pretty good

6:06 * lokien 's jaw dropped

6:06 jonathanj: if i have a structure like [[1 2] [3] [4 5 6 7] [8]] what's the easiest way to end up with the same result as (+ 1 2 3 4 5 6 7 8)?

6:06 TEttinger: it's an extremely simple RNG, but yeah that's pretty good

6:06 I'll benchmark j.u.Random next

6:06 lokien: flatten and apply +?

6:06 jonathanj: (reduce + (mapcat identity xs)) is not really very readable

6:07 lokien: usually mentioning (flatten) gets you lynched

6:07 lokien: jonathanj: lynched? on #clojure? pff

6:07 Bronsa: (transduce cat + xs)

6:08 jonathanj: ,(transduce cat + [[1 2] [3] [4 5 6]])

6:08 clojurebot: 21

6:08 jonathanj: nice

6:08 Bronsa: only works on clojure 1.7+

6:09 jeaye: Given a 2D array in clojure clr, how can I access/update elements?

6:10 I have a System.Single[,]

6:11 TEttinger: jeaye: I wondered the same thing, and the uncertainty in the docs made me hesitant

6:12 jeaye: I'm trying to use Arcadia and Unity is giving me this 2D array.

6:13 lokien: how'd we do it in normal clojure?

6:13 TEttinger: lokien: it turns out java.util.Random is insanely slow generating 64-bit longs

6:13 benchmark still running

6:14 lokien: TEttinger: these random numbers were 64 bit longs?!

6:14 TEttinger: 22,837.146,419 ns to generate 1,000,000,000 longs

6:14 yes

6:14 so what one finishes in 1.2 seconds, the other takes 22.8 seconds

6:15 jeez... I thought LCG RNGs were supposed to be the fastest to make up for their shoddy quality

6:15 lokien: let's write a blogpost about how clojure is faster than java :^) /s

6:16 TEttinger: oh they're both java

6:16 but you could in theory rewrite this in clojure

6:16 jonathanj: jeaye: i think you want aget and aset

6:16 (at least that's how you'd do it with Java arrays)

6:16 lokien: TEttinger: ew, I thought it was in clojure already

6:17 TEttinger: it's easy enough to port

6:17 lokien: I wonder how much slower it would be

6:19 jeaye: jonathanj: Nah, it's not that simple.

6:19 jonathanj: aget fails, saying the array isn't one dimensional.

6:19 Bronsa: in clojure on the jvm aget works for multi dimensional arrays

6:20 jeaye: As mentioned above, this is clojure clr.

6:20 ,(aget [[0 1] [2 3]] 0)

6:20 clojurebot: #error {\n :cause "No matching method found: aget"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching method found: aget"\n :at [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 80]}]\n :trace\n [[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 80]\n [clojure.lang.Reflector invokeStaticMethod "Reflector.java" 207]\n [sandbox$eval47 invokeStat...

6:20 Bronsa: ,(aget (into-array [(object-array [1 2 3])]) 0 0)

6:20 clojurebot: 1

6:21 jonathanj: ,(aget (to-array-2d [[1 2] [3 4]]) 0 0)

6:21 clojurebot: 1

6:22 jeaye: Right.

6:22 clojurebot isn't running on clr though.

6:22 Bronsa: TIL to-array-2d

6:22 https://github.com/clojure/clojure-clr/blob/master/Clojure/Clojure.Source/clojure/core.clj#L3792

6:22 clojure-clr's aget works as the clojure-jvm one

6:23 jonathanj: jeaye: are you passing two indices to aget?

6:23 Bronsa: oh, I see that comment https://github.com/clojure/clojure-clr/blob/master/Clojure/Clojure.Source/clojure/core.clj#L3783

6:23 jeaye: jonathanj: I've tried with both one and two.

6:25 lokien: anyone here using boot instead of leiningen?

6:25 jonathanj: that comment says the author isn't sure how to discern multidim from ragged arrays, but isn't that what Array.Rank does?

6:25 https://msdn.microsoft.com/en-us/library/system.array.rank(v=vs.110).aspx

6:26 jeaye: can't you do (.GetValue the-array idx1 idx2)?

6:26 jeaye: jonathanj: http://dpaste.com/0XCNMZC

6:27 Ah, .GetValue doesn't throw.

6:27 jonathanj: i don't know why the clojure-clr codes doesn't use the .GetValue(Int[]) form

6:28 jeaye: when in doubt interop

6:28 jeaye: Thank you.

6:39 TEttinger: lokien: I told you it was going to be ugly, right?

6:39 ,(do (def state (long-array [9000])) (defn splitmix ^long [] (let [z (aset-long ^longs state 0 (unchecked-add (aget ^longs state 0) -7046029254386353132)) z (unchecked-multiply (bit-xor z (unsigned-bit-shift-right z 30)) -4658895280553007687) z (unchecked-multiply (bit-xor z (unsigned-bit-shift-right z 27)) -7723592293110705685)] (bit-xor z (unsigned-bit-shift-right z 31)))))

6:39 clojurebot: #'sandbox/splitmix

6:39 TEttinger: ,(splitmix)

6:39 clojurebot: -304103417993225237

6:40 TEttinger: ,(time (dotimes [n 1000] (splitmix)))

6:40 clojurebot: "Elapsed time: 3.276121 msecs"\n

6:40 TEttinger: not bad

6:41 ,(time (dotimes [n 1000000000] (splitmix)))

6:41 clojurebot: #error {\n :cause "Unable to resolve symbol: splitmix in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: splitmix in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: splitmi...

6:41 TEttinger: ,(do (def state (long-array [9000])) (defn splitmix ^long [] (let [z (aset-long ^longs state 0 (unchecked-add (aget ^longs state 0) -7046029254386353132)) z (unchecked-multiply (bit-xor z (unsigned-bit-shift-right z 30)) -4658895280553007687) z (unchecked-multiply (bit-xor z (unsigned-bit-shift-right z 27)) -7723592293110705685)] (bit-xor z (unsigned-bit-shift-right z 31)))))

6:41 clojurebot: #'sandbox/splitmix

6:41 TEttinger: ,(time (dotimes [n 1000000000] (splitmix)))

6:41 clojurebot: eval service is offline

6:41 TEttinger: gah

6:41 lokien: D:

6:41 TEttinger: seriously?

6:41 ,(time (dotimes [n 1000000] (splitmix)))

6:41 clojurebot: "Elapsed time: 138.176458 msecs"\n

6:42 TEttinger: ,(/ 1.0 7.0)

6:42 clojurebot: 0.14285714285714285

6:42 TEttinger: still under a seventh of a second for a million

6:42 lokien: it hangs in my repl

6:42 TEttinger: is state defined?

6:43 maybe dotimes doesn't like a certain number

6:43 lokien: (time (dotimes [n 1000000000] (splitmix))) -> "Elapsed time: 52572.653161 msecs"

6:43 TEttinger: hm!

6:43 not as good, wonder why

6:44 lokien: 1000 000 -> 68.64 msecs

6:45 TEttinger: I mean, the java code relies on integer overflow all over the place

6:45 so that's why I needed unchecked variants

6:45 lokien: umm, how?

6:45 TEttinger: it's really ugly in clojure

6:45 lokien: how can you benefit from that?

6:45 TEttinger: most RNGs do

6:45 lokien: TIL programming is spooky

6:46 TEttinger: it assigns massively higher numbers than can fit in 32 or 64 bits, then it wraps around semi-"randomly" (it's 100% predictable but seems random)

6:47 lokien: so, pretty much useless for any crypto stuff

6:47 TEttinger: oh yeah this is not a crypto generator

6:47 in fact

6:47 lokien: /dev/urandom is good enough for crypto junkies, I heard

6:47 TEttinger: I have a function that, given a state, will tell you what state you will have after generating n numbers (or go back to previous states)

6:48 lokien: TEttinger: what for?

6:48 TEttinger: in java it's: long skip(long advance)

6:48 {

6:48 return state += 0x9E3779B97F4A7C15L * advance;

6:48 }

6:48 gah

6:48 that was one line in my IDE!

6:49 however that constant is too large for a long in clojure, you need

6:49 ,(unchecked-long 0x9E3779B97F4A7C15)

6:49 clojurebot: -7046029254386353131

6:49 TEttinger: not sure why Java allows unsigned longs

6:50 and they even compile to signed ones I think

6:50 lokien: can't you use unchecked math at the beginning, once?

6:50 TEttinger: you can set it but not in the bot

6:51 and yes that would help with almost all those long calls

6:51 unsigned-bit-shift-right is not an unchecked thing, it's the >>> operator in Java

6:51 Bronsa: java doesn't allow unsigned longs

6:51 TEttinger: try it Bronsa

6:51 Bronsa: there's no unsigned type in the jvm

6:51 TEttinger: 0x9E3779B97F4A7C15L

6:51 I know

6:52 but that acts like the sign bit is part of the literal and not as a negative sign

6:52 lokien: TEttinger: have you seen benchmark game programs in clojure? they're hella ugly

6:52 TEttinger: in many languages

6:52 lokien: in every language

6:52 it's hand crafting assembly

6:53 I wonder how would it look if all languages just used their idiomatic, readable code

7:33 hey, how can I treat .boot files as .clj files in vim? it's very frustrating that I don't have any highlighting nor auto indentation in here

7:34 I'm using vim-plug if it helps

7:49 jeaye: lokien: au BufNewFile,BufRead *.boot set filetype=clojure

7:53 lokien: jeaye: thank you very much

7:53 jeaye: Sure.

7:54 lokien: I was desperate enough to mv build.boot build.boot.clj :(

9:10 TMA: lokien: also adding this line to the bottom/top several lines of the file helps ; vim: set ft=clojure :

9:14 lokien: see :help modeline for details

9:21 gfredericks: lokien: did TEttinger3 point to https://www.youtube.com/watch?v=u0t-6lUvXHo and https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/random.clj?

9:24 lokien: gfredericks: no

9:25 TMA: I'll check this out

9:26 TMA: will this set every file to be a clojurey one?

9:29 gfredericks: nice diagrams. I'll bookmark it and watch it after I'm done with cljs intro

9:29 * gfredericks thumbs up

9:45 lokien: noncom: hello

10:08 lokien_: gfredericks: I got lost after like 15 minutes

10:09 but it's an interesting talk

10:26 gfredericks: haha

10:26 my apologies

10:27 communicating is hard

10:30 lokien_: gfredericks: nah, that's my fault

10:31 I don't get concepts that quickly and I barely know rng stuff

10:43 TMA: lokien_: the jeaye's method [if put into .vimrc] will make every *.boot file clojurey -- my suggestion will make the file this modeline is in clojurey, but not others

10:44 lokien_: the jeaye's method will make all *.boot clojurey just for you, whereas the modeline will make the particular file it clojurey for everyone using vim

10:45 lokien_: these are the main tradeoffs

10:45 lokien_: TMA: okay, I'll use your solution then

10:45 TMA: *file it is present in

11:06 qsys: if I have a collection of items and want to turn this into a list of vectors of every first and third item... what's the best/cleanest way to do that? (item1 item2 item3 item4 item5 item6) shoud be transformed into ([item1 item3] [item4 item6])

11:07 justin_smith: ,(map (fn [[a b c]] [a c]) (partition-all 3 (range 1 7)))

11:07 clojurebot: ([1 3] [4 6])

11:08 qsys: lol, easy, thx!

11:10 it's always easier than I think...

11:10 justin_smith: the more you use all the core functions, the easier it is to see how to use and compose them to get your result

11:11 qsys: it's partition-all I couldn't think of :p

11:22 justin_smith: in case one forgets it exists, it could be something like --

11:22 ,(defn part ([n coll] (part n n coll)) ([n step coll] (when (seq coll) (lazy-seq (cons (take n coll) (part n step (drop step coll)))))))

11:22 clojurebot: #'sandbox/part

11:22 justin_smith: ,(part 3 (range 1 7))

11:22 clojurebot: ((1 2 3) (4 5 6))

11:27 late20: hey! i have (() ([1 2]) () ([3 4])) and would need to get ([1 2][3 4]), so need to get rid of the inner lists. can't figure out any good way...

11:27 justin_smith: ,(filter seq ' (() ([1 2]) () ([3 4])) )

11:27 clojurebot: (([1 2]) ([3 4]))

11:28 justin_smith: ahh, wait

11:28 ,(apply concat ' (() ([1 2]) () ([3 4])) )

11:28 clojurebot: ([1 2] [3 4])

11:28 justin_smith: late20: if you got that list via "map", you can just replace "map" with "mapcat" btw

11:37 engblom: I wonder if refs is the tool I need in this case: I a single state I need want to update in a threadsafe way. The state update function takes a few steps and while it is running, I want reading of the state to be blocked.

11:37 justin_smith: engblom: there is nothing in clojure that blocks reading while an update is in process

11:37 engblom: with refs, agents, atoms, you just read the old value while it is mid update

11:38 engblom: justin_smith: Is not dosync doing it?

11:38 justin_smith: no

11:38 engblom: dosync makes sure they read the old value, or the final one

11:38 it doesn't block reading

11:38 engblom: What if I wrap the places where it is read also with a dosync?

11:39 late20: justin_smith: sweet, thanks!

11:39 justin_smith: engblom: then you'd get retries, and eventually it would return the new value

11:39 engblom: but it's still not blocking, it's just forcing the code to run again

11:40 engblom: justin_smith: So the effect is still that I get the new value and not the old if I wrap the @ with dosync?

11:40 justin_smith: if there's any overlap, yeah

11:40 engblom: Ok, thanks! That is what I want

11:42 My exact case is this: If I have a stepper motor and its 8 phases that I want to store in a ref. I need to both change the ref and the stepper motor together, so if anything would want to read the state of the motor, it would always be right.

11:48 lokien_: I'm trying to learn cljs, but I'm spooked by html and css. do we have any wrapper around these?

12:03 favetelinguis: ,(let [a "3"] (case a (str 3) "ETT"))

12:03 clojurebot: #error {\n :cause "No matching clause: 3"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching clause: 3"\n :at [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]\n [clojure.lang.Compiler eval "Compiler.java" 68...

12:03 justin_smith: favetelinguis: case only allows literals

12:04 favetelinguis: that clause matches str or 3, but not "3"

12:04 ,(case str (str 3) :OK)

12:04 clojurebot: #error {\n :cause "No matching clause: clojure.core$str@e9ea392"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching clause: clojure.core$str@e9ea392"\n :at [sandbox$eval51 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval51 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval51 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]\n ...

12:04 justin_smith: hmm

12:04 ,(case :str (:str 3) :OK)

12:04 clojurebot: :OK

12:06 favetelinguis: what i want to do is something like this

12:08 ,(let [in-msg :key2 m {:a :key1 :b :key2}] (case in-msg (:a m) "A" (:b m) "B"))

12:08 clojurebot: #error {\n :cause "Duplicate case test constant: m"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: Duplicate case test constant: m, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.IllegalArgumentException\n :message "Duplicate case test constant: m"\n :at [clojure.co...

12:08 justin_smith: favetelinguis: right, that is impossible

12:08 use cond instead

12:08 favetelinguis: ok thanks will look that up ty

12:08 justin_smith: case only allows literals

12:13 bcoburn_: ,(let [a "3"] (case a "3" "ETT"))

12:13 clojurebot: "ETT"

12:14 bcoburn_: oh I see

12:14 Ignore my sillyness

12:15 justin_smith: ,(case 'str (str 3) :OK)

12:15 clojurebot: :OK

13:01 favetelinguis: are there any restrictions on how to require records? im trying to require a defrecord but getting the error it cant be found...

13:04 justin_smith: you require namespaces, not records

13:04 you can import the class, but the class won't exist for importing until the namespace is required

13:07 favetelinguis: hmm i have a prismatic schema required as s then i have a s/defrecord MyTypeSchema in ns a, then in ns b i want to do (s/validate MyTypeSchema in-value)

13:07 justin_smith: then you need (:require [a :refer [MyTypeSchema]])

13:08 or you can do a normal require, and use a.MyTypeSchema

13:08 favetelinguis: getting an error when doing that, but then i know it shuld be no problems, must be somthing else then

13:08 justin_smith: sorry, a/MyTypeSchema

13:09 favetelinguis: "an error"

13:09 favetelinguis: No such var...

13:13 anyone uses cider in emacs here and knows how to jump to file of error from the error buffer? I found M-g s should do this but it does not work...

13:49 justin_smith: no mather what i try im not able to use a record defined in ns a in ns b, im following the recomendations of first require the ns a than explicitly import the record but still the var can not be found, might there be somthing else im missing?

13:58 newer mind i was using it wrong with prismatic schema

14:01 justin_smith: favetelinguis: working demo https://gist.github.com/noisesmith/265d375137b842d055dd

14:01 but it sounds like you solved it already

14:34 favetelinguis: justin_smith: the thing is i wanted to record class and not the constructor function

14:35 but i got it working when i realised that the imported class is accesed using ClassName. not only ClassName :)

14:37 if an exception is thrown in a go block will that be propagated and diplayed or will the go block only siliently die?

14:41 (timbre/info "HERE")

14:42 This is what i want to do but i want to exeption to be propagated no EX never prints (a/go (Thread/sleep 2000) (println "ONE") (throw (Exception. "EX")) (println "TWO"))

14:43 justin_smith: favetelinguis: yes, you need a try catch that prints inside the go block if you want it to print

14:44 favetelinguis: also, updated that example https://gist.github.com/noisesmith/265d375137b842d055dd

14:51 favetelinguis: thanks, however i never go that workign with the prismatic schema defrecord macro, and use it with validate.

16:15 lambda-11235: When is hasheq used for symbols?

16:57 gfredericks: probably when putting them in a hash map?

16:57 lokien_: what does ^ before a value do? it's hard to google

16:57 gfredericks: ,(hash 'foo)

16:58 clojurebot: -1385541733

16:58 gfredericks: ,(meta ' ^foo bar)

16:58 clojurebot: {:tag foo}

16:58 gfredericks: lokien_: ^ is part of metadata syntax

16:58 it doesn't go before a value by itself

16:58 ,(meta ' ^a-symbol ^:a-keyword ^{:a :map} the-real-value)

16:58 clojurebot: {:a :map, :a-keyword true, :tag a-symbol}

16:59 gfredericks: ↑ three had syntaxes

16:59 s/had/hat/

17:00 ,(set! *print-meta* true)

17:00 clojurebot: #error {\n :cause "Can't change/establish root binding of: *print-meta* with set"\n :via\n [{:type java.lang.IllegalStateException\n :message "Can't change/establish root binding of: *print-meta* with set"\n :at [clojure.lang.Var set "Var.java" 221]}]\n :trace\n [[clojure.lang.Var set "Var.java" 221]\n [sandbox$eval97 invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$eval97 invoke "NO_SOURCE_FILE...

17:00 lokien_: gfredericks: why would I need that?

17:00 gfredericks: ,(binding [*print-meta* true] (print-str 'foo))

17:00 clojurebot: "foo"

17:00 gfredericks: ,(binding [*print-meta* true] (print-str '^a-symbol ^:a-keyword ^{:a :map} foo))

17:00 clojurebot: "foo"

17:01 gfredericks: hrmph

17:01 Mordus: Is it an antipattern to use an input channel and output channel when using something like Chord? The documentation talks about the channels being two way, but I can't wrap my head around how to use the channel in both directions

17:01 gfredericks: lokien_: it's mostly used for compiler flags & annotations

17:01 e.g., type-hints

17:02 lokien_: ^{:key item} - it's from reagent intro.

17:03 gfredericks: whenever you see a form like that, it's attaching metadata to the next thing

17:03 so if we did this:

17:03 lokien_: it says something about unique keys to every item

17:03 gfredericks: ,^{:key item}

17:03 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:03 gfredericks: we'd get a syntax error since there was nothing to add the metadata to

17:03 lokien_: so we'd need item declared earlier, right?

17:04 gfredericks: yeah that too

17:04 ,^{:key item} [:still-won't-work]

17:04 clojurebot: #error {\n :cause "Unable to resolve symbol: item in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: item in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: item in this co...

17:04 lokien_: (why would it work anyway?)

17:15 justin_smith: lokien_: reagent uses metadata before items in collections in order to track the "identity" to know how items should move if the list is altered

17:15 lokien_: since the object identity isn't helpful with clojure, it needs some other marker to know which entry is which in a table or list etc.

17:17 lokien_: justin_smith: well, thanks. is there any good tut about reagent besides intro?

17:17 I hate how clojure tutorials assumed I know java, and now cljs tutorials assume I know js and html

17:18 ridcully_: i dont use reagent, but "the others" usually allow the :key just fine with the attributes

17:19 lokien_: ridcully_: kay, I'll take this approach

17:19 ridcully_: at least give it a try. e.g. [:td {:key ...} "zerg"]

17:20 Deraen: lokien_: Re-frame has good Reagent tutorials: https://github.com/Day8/re-frame/wiki#reagent-tutorials

17:20 lokien_: I don't know with what, I don't understand a word from this weird code :^)

17:21 Deraen: you saved my life. they're kind of short though

17:22 Deraen: And yes, Reagent allows key attribute. Metadata is useful when the element is another component, ^{:key 1} [list-item item]

17:34 austrinus: W abh-

17:40 princeso: how do we name it when we do this (:key {:key 1}), im calling it like 'left key call'

17:41 justin_smith: invoking a keyword

17:41 calling a keyword

17:41 if it's not on the left, you aren't calling it

17:41 ,(:ho :ho :ho)

17:41 clojurebot: :ho

17:42 lokien_: and what does @ do, before a value?

17:42 kwladyka: What is the point of "complement" function? Personally i feel this is a first step to make unnecessary functions in Clojure.

17:42 justin_smith: ,'@foo

17:42 clojurebot: (clojure.core/deref foo)

17:42 justin_smith: lokien_: ^

17:43 kwladyka: it's extremely useful

17:43 ,(def not-zero? (complement zero?))

17:43 clojurebot: #'sandbox/not-zero?

17:43 kwladyka: justin_smith why not "not" instead? :)

17:43 justin_smith: ,(not-zero? 1)

17:43 clojurebot: true

17:43 justin_smith: kwladyka: try doing that with not

17:44 kwladyka: not is for negating a single result, complement is for creating the opposite predicate

17:44 these are not the same thing

17:46 lokien_: justin_smith: eww, all these complicated words in docs.. why can't I just (println "hello world") till my program builds itself

17:49 princeso: justin_smith : thx . :D

17:49 kwladyka: justin_smith ok it makes a few lines less but the true value will be if editors could show parameters from inner function

17:49 justin_smith: lokien_: in my experience some programming concepts are not useful until you make the terrible mistakes that go with not understanding them yet

17:52 lokien_: you can consider each big word you don't get an attempted solution for a mistake you haven't made (or maybe made but didn't understood) yet

17:53 lokien_: justin_smith: I'll read "clojure for the brave and true" chapter about it, so I won't do this mistake (which I didn't do) again

17:53 justin_smith: heh

17:54 Glenjamin: the trick when learning programming (imo), is to realise that mistakes don't really cost anything

17:54 you can just try stuff, and if it doesn't work, try something else

17:54 justin_smith: Glenjamin: depends on what time's worth, yeah

17:54 Glenjamin: it's not like building a bridge, or a wall

17:55 lokien_: anyway, does anyone know where is j-pb? he promised to help me and now he's gone

17:55 bcoburn_: I find that I waste less time making mistakes than I do worrying about all the mistakes I might be making

17:55 kwladyka: lokien_ i really recommend watch clojure inside out if you are learning and want to understand what is and what not is Clojure

17:56 lokien_: kwladyka: is it a talk or something?

17:56 kwladyka: lokien_ video

17:56 "clojure inside out" - the title

17:56 lokien_: kwladyka: another sleepless night, thanks

17:57 kwladyka: ;)

17:57 lokien_: Glenjamin: I don't like any of this cljs stuff, how do I build a website in clojure? :^)

17:59 kwladyka: lokien_ there you have courses http://www.purelyfunctional.tv , one of them is about ClojureScript and OM

17:59 and generally they will help you to learn faster

18:00 lokien_: kwladyka: are they free? this site is so ugly on mobile

18:00 welp, they aren't

18:00 kwladyka: lokien_ no, you have to pay but it is worth that

18:00 generally things where you have to pay are better...

18:00 lokien_: the problem is, I have like four dollars

18:01 which is kinda good, since I had three last week

18:01 kernasi: lokien_, that website looks like shit even on a pc with a big screen :)

18:02 lokien_: kernasi: why would I pay them then /:

18:02 I know, I know, maybe courses are okay

18:02 kernasi: heh

18:02 kwladyka: 4clojure.com <- this is free place where you can learn a lot

18:03 just add the best users to fallow they solutions

18:03 and after do task you can compare your solution with they

18:03 and learn a lot

18:03 kernasi: kwladyka, that's useful, thanks

18:04 lokien_: kwladyka: I knew that it existed, I just want to learn how to use react :^(

18:04 kernasi: eww :P

18:05 kwladyka, nice, now I know how I can waste my weekend :)

18:05 kwladyka: lokien_ just choose Rum, Om or another tool and start doing it :)

18:06 lokien_: kernasi: have you seen advent of code? :^)

18:06 kwladyka: right now I'm trying to get reagent to work, kind of

18:07 kernasi: lokien_, no, just projecteuler

18:07 lokien_: kernasi: check it out

18:10 Frozenlock: Is there a situation where 'with-test' is acceptable? It seems I always only see separate test namespaces.

18:42 gfredericks: one question you might find relevant is if `lein test` supports it out of the box

19:25 lrc: trying to reify a ConvergenceChecker from http://goo.gl/7B5Q4q. Clojure can't find matching method, and none of my attempts to hint the types have worked either. Is the use of <PAIR> complicating things, I wonder...

19:28 justin_smith: you shouldn't need to hint the method, does your reify provide "this"? because that's manditory and not providing it can make it look like an invalid method

19:29 (reify ConvergenceChecker (converged [this iteration previous current] ...))

19:30 lrc: yup, my code looks just like that. It gets a reflection warning in lein check, though. (Maybe that's not authoritative?)

19:32 actually, hold on a moment. The reflection warning is actually further in the method. Maybe I have to hint the call.

19:34 that was it. When I got reflection warnings further along, I tried to include the type hint in the parameter list, but then Clojure couldn't match the method for reify.

19:34 Adding a type hint at the call site for those last two params has done the trick. Thank you!

19:34 justin_smith: np, glad you got it sorted out

21:49 Mordus: I just started an app using chord, and I'm noticing some strange behavior, I can only send 128 messages through my websocket. Anyone experience this? Is there a setting that's not right or something?

21:54 hiredman: well, there are three places to check, the producing side, the consuming side, and the middle

21:54 the first thing to check is, are their errors in any of those three places

21:55 stacktraces, exceptions, entries in the console log or however you find errors in the browser

21:57 Mordus: hiredman, I'm an idiot. Thank you. Websockets were timing out

22:00 hiredman: go forth and debug

22:01 pilne: gosh darn it, finding a color theme in atom that will hilight & is proving to be quite difficult

23:11 lambda-11235: Does comparing symbols have a time complexity of O(1)?

23:14 justin_smith: lambda-11235: worst case is two uninterned symbols, that are long and differ at the end I think...

23:14 this might be where hashCode comes in...

23:20 lambda-11235: justin_smith: But symbols are interned in clojure, and compared using this fact, right?

23:21 It's hard to tell looking at Symbol.java.

23:25 justin_smith: lambda-11235: I am not certain they are all interned - if they are the overhead is all aborbed at symbol creation time of course

23:25 lambda-11235: I'm going to do a microbenchmark....

23:31 lambda-11235: Symbol.intern doesn't appear to actually do anything, what am I missing?

23:32 justin_smith: lambda-11235: looks like ~O(n) imperically https://gist.github.com/noisesmith/2abff5c61244452835b4

23:32 empirically, however we spell that

23:32 sorry, I mean O(1)

23:34 lambda-11235: I assume you are looking here? https://gist.github.com/noisesmith/2abff5c61244452835b4

23:36 lambda-11235: justin_smith: At the site you just posted, yeah.

23:36 justin_smith: oops, I didn't mean to paste my gist twice

23:37 I meant to link to here https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Symbol.java#L58

23:38 lambda-11235: justin_smith: That, and the method right above it.

Logging service provided by n01se.net