#clojure log - Dec 31 2015

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

7:21 lokien: Is if in an if acceptable?

8:29 favetelinguis: what is the easy way to make two numbers 123 456.2 into one number 123456.2

8:34 MJB47: ,(read-string (str 123 456.2)) ; favetelinguis

8:34 clojurebot: 123456.2

9:27 favetelinguis: ,(+ 1 2)

9:27 clojurebot: 3

11:42 justin_smith: ,(* 84 24) ; TIL it's the hear for default TTY resolution

11:42 clojurebot: 2016

11:42 justin_smith: err

11:42 yeah

11:42 err wait, I fucked that up, it's 84x24 is my new years resolution

11:42 yeah that's the ticket

14:28 zacts: I just got a fresh copy of new Joy of Clojure by Manning Press in the mail from a friend who ordered it when it was a MEAP

14:29 I can't wait to read it

14:34 justin_smith: it's a good book

14:40 dhz_: ready for new year :D http://s16.postimg.org/xhogpbk1v/image.jpg http://s23.postimg.org/hdi9oiwex/image.jpg

15:09 amalloy: justin_smith: isn't 80x24 the standard anyway?

15:10 justin_smith: amalloy: yes, that was part of the problem

15:10 just one of the ways I butchered that joke

15:43 nwallace: Hey everybody. I'm having an issue trying to learn Om/Next... I can't seem to read any application state in a new component I've defined. I can read state just fine in the root component that renders the whole app, but in a new sub-component, I tried to use the same code to read state into the subcomponent and it's not working. If anyone's interested in helping, please message me :)

16:00 chouser: What in the world am I supposed to do when boot keeps saying "Implicit target dir is deprecated,"?

16:01 I'm just following the readme, but the tool is yelling at me. :-(

16:11 amalloy: chouser: from a quick look at the boot source: try setting :target-path to "target"? i haven't used boot so i don't know how you would do that, but it is looking in the boot environment for a thing called :target-path before issuing that warning

16:12 chouser: amalloy: Thanks. I've tried that. It also says I should use the 'target' task, and I'm doing that now too.

16:13 So far, the only way I can get it to stop complaining is to also set BOOT_EMIT_TARGET=no as it suggests.

16:13 Maybe I have to both set the target and also explicitly tell it to stop warning??

16:15 amalloy: *shrug* no help from me, i'm afraid

16:15 chouser: thanks for looking. :-)

16:15 I don't know why I'm trying boot now, when I'm really supposed to be trying cljs+node.js

16:16 amalloy: 2016 resolution: try the fun things instead of the right things

16:19 chouser: I like it

16:21 I'm gonna put a raspberry pi running node.js into a scale sailboat and try to control it via wifi from a phone. That sounds more fun that right, don't you think?

16:22 justin_smith: that sounds awesome

16:23 chouser: well, we'll see how far I get before I give up. :-P

16:23 justin_smith: also, I've had decent luck running a clojure jar on my raspi. not lein or anything, just a built jar starting up to a repl. It leaves plenty of free heap space, and starts in a semi-reasonable period of time with the jvm that ships on the pi.

16:23 well, in the default pi2 image that is

16:24 chouser: justin_smith: Hm, good to know. I think I'll pursue node.js first, but it's good to know that standard clojure might be an option too.

17:16 featheredtoast: hey guys, happy clojuring over my winter break! is there anyone here who can explain the cryptic syntax in the core.logic tutorial here? https://github.com/swannodette/logic-tutorial/blob/master/src/logic_tutorial/tut3.clj#L7

17:29 turbofail: featheredtoast: are you specifically curious about that particular line?

17:31 featheredtoast: turbofail: syntax/symbols mostly. I'm unfamiliar with the ?r and '.' within a vector

17:31 turbofail: well '.' within a vector doesn't really mean anything, that's a syntax borrowed from scheme

17:32 in this context it means "match the rest of this sequence," kind of like how you'd use & in an argument vector

17:33 ?r is just a logic variable that we're binding to the rest of the sequence

17:33 featheredtoast: ooh, gotcha. Thanks! that's what I kinda assumed, but the docs on core.logic don't seem to be fully fleshed out

17:33 dnolen: turbofail: `defne` gives you Prolog style unification on fn arguments

17:33 featheredtoast: ^

17:34 featheredtoast: thanks guys

17:35 dnolen: it just sugar to remove tedious conde writing

18:01 domokato: what's the simplest way to convert a boolean into number 0 or 1, and back again?

18:03 justin_smith: (map {0 false 1 true} [1 0 1 1 1 0 0 1])

18:03 ,(map {0 false 1 true} [1 0 1 1 1 0 0 1])

18:03 clojurebot: (true false true true true ...)

18:03 MJB47: cant you do

18:03 justin_smith: ,(map {false 0 true 1} [true false false true false true true true])

18:03 MJB47: ,(boolean 0)

18:03 clojurebot: (1 0 0 1 0 ...)

18:03 true

18:03 MJB47: ,(boolean 1)

18:03 clojurebot: true

18:03 MJB47: nvm

18:03 justin_smith: MJB47: zeroes and ones are both true

18:03 MJB47: yer i just remembered

18:04 AimHere: Are you sure that the only truthy value you want is 1?

18:04 justin_smith: AimHere: good point

18:05 #({0 false} % true) is also an option

18:05 ,(map (complement zero?) [1 0 1 0 1 1 1 0 0])

18:05 clojurebot: (true false true false true ...)

18:05 justin_smith: (complement zero?) feels clever

18:06 domokato: justin_smith: it does!

18:06 i may just use the first one. seems clearest

18:06 thx!

18:08 tolstoy: Lament for the venerable if experssion.... ;) (map #(if (zero? %) false true) [1 0 1 1 0 0])

18:08 justin_smith: tolstoy: but it's so verbose!

18:09 tolstoy: and that's identical to (complement zero?)

18:09 tolstoy: ik, thx. ;)

18:09 domokato: now i wonder which is faster, the map or the complement zero?

18:09 justin_smith: domokato: I know a good way to check (checking...)

18:13 tolstoy: ,(map #(condp = 1 true 0 false) [1 0 1])

18:13 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/eval25/fn--26>

18:13 justin_smith: tolstoy: needs a % in there

18:13 tolstoy: Yeah, I always screw up condp.

18:13 ,(map #(condp = % 1 true 0 false) [1 0 1])

18:14 clojurebot: (true false true)

18:14 tolstoy: I like the if better.

18:14 ,(map #(get {1 true 0 false} %) [1 0 1])

18:14 clojurebot: (true false true)

18:15 justin_smith: tolstoy: that's silly

18:15 #(get {1 true 0 false} %) is just {1 true 0 false}

18:16 I mean sure, they are not identical, but they don't differ in a way that matters here

18:16 tolstoy: ,(map {1 true 2 false} [1 0 1 1])

18:16 clojurebot: (true nil true true)

18:17 tolstoy: ,(map {1 true 0 false} [1 0 1 1])

18:17 clojurebot: (true false true true)

18:17 tolstoy: Neat. ;)

18:22 justin_smith: OK, just spent some time messing around - all the options took 9.x ns

18:22 except the map literal, which only took 7.x

18:22 but, if I used a def, then used that instead of a literal, it went up to 9.x

18:22 weird!

18:22 neoncontrails: (justin_smith: map literal... you mean tolstoy's suggestion, right?

18:23 justin_smith: I mean my first suggestion

18:23 domokato: that works out. turns out i'm using a literal, not a def

18:23 justin_smith: {0 false 1 true} that's a map literal

18:23 neoncontrails: heh apparently all it takes is 15 minutes of casually coding in Clojure to make me go left-parenthesis mad

18:24 domokato: justin_smith: thx dude

18:25 neoncontrails: justin_smith: that makes sense to me actually. I was curious how complement could compete with a literal mapping, considering the complement solution would also work for non-binary numbers

18:26 justin_smith: yeah, the (complement zero?) one performed about the same

18:26 they were all pretty close

18:30 amalloy: the main overhead is probably allocating all the cons cells

18:31 how you convert int->bool got lost in the noise

18:31 justin_smith: true

18:32 * justin_smith tries with doseq instead of map now

18:36 justin_smith: amalloy: d'oh - criterium doesn't doall on top level laziness :P

18:36 * justin_smith puts on his dunce cap.

18:43 justin_smith: the numbers are in! if was fastest https://gist.github.com/noisesmith/b3ea6e44615613a0d458

18:44 tolstoy: "if" is fastest? Heh. But it's so ... mundane!

18:45 justin_smith: :)

18:47 neoncontrails: justin_smith: is the standard 'time' library flawed?

18:47 I noticed you're using a third-party extension

18:48 justin_smith: neoncontrails: it doesn't reliably make hotspot kick in

18:48 criterium is much more reliable in its measurements

18:48 https://github.com/hugoduncan/criterium

18:49 neoncontrails: Interesting. I had no idea benchmarking on the JVM was fraught with peril

18:50 justin_smith: neoncontrails: the automatic runtime optimization thing means getting a good measurement is tricky

18:51 also, regardless of platform, statistical analysis of multiple runs is much more informative than a strict average

18:51 neoncontrails: I see. Both good points.

18:51 rhg135: is assuming hotspot always optimizes a good idea?

18:51 justin_smith: given that your computer is probably doing more than just running the benchmarks

18:51 rhg135: it is better at optimizing some things than others, there are flags to turn it on or off, and flags to make it operate verbosely

18:52 rhg135: by default "lein repl" will disable hotspot, for example

18:53 rhg135: I thought hotspot will prioritize "hot" code such as loops which means most code is not in practice

18:54 justin_smith: rhg135: it is expensive to generate the optimized version, so it only optimizes things that get run frequently

18:55 rhg135: and then, it can only optimize so much, depending on the structure of your code - can it inline anything? can it unbox anything? etc. many "dynamic" things that allow runtime redefinition prevent optimization (because it can't safely do the transformation and ensure 100% correctness)

18:56 rhg135: I found a really awesome video about what hotspot can and cannot inline, let me see if I can find it again

18:56 rhg135: yeah. I guees that'- a problem with microbenchmarks

18:57 it'- always better to see what is actually happening

18:57 justin_smith: yes, microbenchmarks can answer micro-questions, but in a real app most of your work is finding the bottleneck where the optimization even helps

18:58 rhg135: https://www.youtube.com/watch?v=0Yud4Q2HEz4

19:03 rhg135: thx mate

21:16 ben_vulpes: is there a slick way to de-namespace keywords in a map?

21:16 justin_smith: ben_vulpes: (comp keyword name)

21:16 I mean that and your typical map-keys f of course

21:16 ben_vulpes: justin_smith: quickest hand in the west

21:17 *pow* *pow*

21:17 thanks, justin_smith

22:24 justin_smith: TIL 2016 is the number of edges of a fully connected undirected graph with 64 vertices.

22:24 TEttinger: huh!

22:25 what about 65 vertices?

22:25 when's the next year :)

22:25 justin_smith: n(n-1)/2

22:25 TEttinger: oh that's that one

22:26 ,(/ (* 65 64) 2)

22:26 clojurebot: 2080

22:26 TEttinger: oh, maybe in some of our lifetimes

22:26 justin_smith: ,(defn uni-graph-edges [n] (* n (dec n) (/ n 2))

22:26 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

22:26 justin_smith: ,(defn uni-graph-edges [n] (* n (dec n) (/ n 2)))

22:26 clojurebot: #'sandbox/uni-graph-edges

22:26 TEttinger: I'd be 92...

22:26 justin_smith: (uni-graph-edges 64)

22:26 ,(uni-graph-edges 64)

22:26 clojurebot: 129024

22:26 justin_smith: err...

22:26 oops!

22:27 ,(defn uni-graph-edges [n] (* n (dec n) 0.5))

22:27 clojurebot: #'sandbox/uni-graph-edges

22:27 justin_smith: ,(uni-graph-edges 64)

22:27 clojurebot: 2016.0

22:27 justin_smith: ,(uni-graph-edges 63)

22:27 clojurebot: 1953.0

22:27 justin_smith: first one since '53

22:28 ,(uni-graph-edges 65)

22:28 clojurebot: 2080.0

22:28 justin_smith: yeah, it'll be a while

22:29 ,2r11111100000

22:29 clojurebot: 2016

22:29 justin_smith: !

22:32 ,2r11111011111 ; last year was a palindrome

22:32 clojurebot: 2015

22:32 justin_smith: ,2r11111111111 ; next one

22:32 clojurebot: 2047

22:32 MJB47: now that youve pointed that out

22:32 you have to make an algorithm

22:32 justin_smith: oooh

22:32 MJB47: to find all of htem

22:32 lazily

22:33 justin_smith: fun

22:33 MJB47: happy new year!

22:38 justin_smith: ,(.reverse 42)

22:38 clojurebot: #error {\n :cause "No matching field found: reverse for class java.lang.Long"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching field found: reverse for class java.lang.Long"\n :at [clojure.lang.Reflector getInstanceField "Reflector.java" 271]}]\n :trace\n [[clojure.lang.Reflector getInstanceField "Reflector.java" 271]\n [clojure.lang.Reflector invokeNoArgInstanceMem...

22:38 justin_smith: ,(Long/reverse 42)

22:38 clojurebot: 6052837899185946624

22:38 justin_smith: hmm...

22:40 ,(bit-shift-right (Long/reverse 42) 60)

22:40 clojurebot: 5

22:40 justin_smith: ,(bit-shift-right (Long/reverse 5) 60)

22:40 clojurebot: -6

22:40 justin_smith: :P

22:41 sign extension!

22:42 amalloy: didn't something like logical-bit-shift-right get added?

22:43 justin_smith: ,(unsigned-bit-shift-right (Long/reverse 5) 60)

22:43 clojurebot: 10

22:43 justin_smith: hmm

22:43 so I'm still not doing it right, but that's the ticket, thanks

22:45 (iterate #(unsigned-bit-shift-right (Long/reverse %) 58) 42)

22:45 ,(iterate #(unsigned-bit-shift-right (Long/reverse %) 58) 42)

22:45 clojurebot: (42 21 42 21 42 ...)

22:46 justin_smith: ,(iterate #(unsigned-bit-shift-right (Long/reverse %) 53) 2015)

22:46 clojurebot: (2015 2015 2015 2015 2015 ...)

22:46 TEttinger: http://clojuredocs.org/clojure.core/unsigned-bit-shift-right

22:46 ah you found it

22:46 justin_smith: so now I just need to derive the magic number

22:46 for the bit shift

22:50 ,(defn bit-palindrome? [n] (= n (unsigned-bit-shift-right (Long/reverse n) (Long/numberOfLeadingZeros n))))

22:50 clojurebot: #'sandbox/bit-palindrome?

22:50 justin_smith: ,(bit-palindrome? 2015)

22:50 clojurebot: true

22:50 justin_smith: ,(bit-palindrome? 2047)

22:50 clojurebot: true

22:50 justin_smith: ,(bit-palindrome? 2016)

22:51 clojurebot: false

22:51 justin_smith: MJB47: did it!

22:51 MJB47: not exactly what i asked, but good enough

22:51 congrats

22:51 you got 1 internet point

22:51 :)

22:51 justin_smith: ,(filter bit-palindrome? range)

22:51 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$range>

22:51 justin_smith: ,(filter bit-palindrome? (range)) ; OK fine

22:51 clojurebot: (0 1 3 5 7 ...)

22:52 MJB47: :P

22:52 kenrestivo: i'm trying to combine lein do, lein update-in, and lein with-profile, and not having any luck

22:52 TEttinger: ,31r231

22:52 clojurebot: 2016

22:52 kenrestivo: what's the right Magickal Incantation to have a do, update-in, and with-profile coexisting peacefully?

22:53 justin_smith: kenrestivo: maybe it would help if you were trying to trampoline also

22:55 TEttinger: here's a fun one from r/math: (6!! - 6) 6!!

22:55 kenrestivo: nope, that'd just make it more complex

22:56 i'm gettign EOF while reading string

22:56 i have to do these things sorry. i need lean profile, i need to run a compile task, and i need to inject the keystore password via update-in

22:56 since that ain't going in my project.clj

22:58 justin_smith: kenrestivo: are you sure the keystore password is needed in order to compile - can't it be factored out of that?

22:59 kenrestivo: nope

22:59 hmm, i found a way around the eOF complaint

22:59 \\"password\\"

23:01 TEttinger: justin_smith: did I do it right?

23:01 https://www.refheap.com/113279

23:02 justin_smith: I'm guessing no!

23:04 kenrestivo: thogh it mangled the password, so that didn't help :( ugh, nevermind. 10 more minutes with this then i'll get bored and move on

23:05 justin_smith: TEttinger: I'm thinking I misread the thing... https://www.reddit.com/r/math/comments/3yukgr/answer_2016/cygy3nm

23:05 TEttinger: yeah I screwed up slightly https://www.refheap.com/113280

23:05 justin_smith: TEttinger: or perhaps I am gullible

23:06 TEttinger: maybe OP of the formula got an overflow and didn't realize?

23:06 TEttinger: or maybe !! is choose

23:06 it's in combinatorics

23:07 justin_smith: AH

23:07 that makes a lot more sense, thanks

23:07 I have not seen that notation for choose before though

23:09 TEttinger: double factorial

23:09 http://reference.wolfram.com/language/ref/Factorial2.html

23:10 kenrestivo: solveded: lein with-profile lean do update-in :android assoc :keypass "\"pass\"" :storepass "\"pass\"" -- droid apk

23:10 \"\"\\ok?\""\"?

23:10 justin_smith: kenrestivo: "\"pass\"" could be '"pass"'

23:10 kenrestivo: aye, that'd work too, thanks

23:11 justin_smith: kenrestivo: the command will still work, but can start faster, if you insert "trampoline" before with-profile

23:11 sorry about the bad joke though

23:12 ,(defn bit-palindrome? [n] (= n (unsigned-bit-shift-right (Long/reverse n) (Long/numberOfLeadingZeros n))))

23:12 clojurebot: #'sandbox/bit-palindrome?

23:12 justin_smith: ,(filter bit-palindrome? (range 2047 2050))

23:12 clojurebot: (2047 2049)

23:12 justin_smith: cool

23:14 TEttinger: ,(let [!! (reduce * (range 2 7 2))] (* (- !! 6) !!))

23:14 clojurebot: 2016

23:15 justin_smith: ,[(Long/toString 2047, 2) (Long/toString 2049, 2)] ; d'oh, of course

23:15 clojurebot: ["11111111111" "100000000001"]

23:17 TEttinger: ,(defn radit-palindrome [n radix] (= (seq (Long/toString n radix)) (reverse (Long/toString n radix))))

23:17 clojurebot: #'sandbox/radit-palindrome

23:17 TEttinger: ,(radit-palindrome 3r222 3)

23:17 clojurebot: true

23:17 TEttinger: ,(radit-palindrome 3r220 3)

23:17 clojurebot: false

23:17 justin_smith: nice!

23:17 TEttinger: ,(radit-palindrome 3rZZZ 36)

23:17 clojurebot: #<NumberFormatException java.lang.NumberFormatException: For input string: "ZZZ">

23:17 TEttinger: ,(radit-palindrome 36rZZZ 36)

23:17 clojurebot: true

23:24 justin_smith: TEttinger: if it wasn't clear, I intentionally used the string rep version for the binary palindrome one, because I knew there had to be an elegant way to do it directly with bit ops

23:24 *intentionally did not use

23:24 but the general version is of course a lot easier with the strings

23:31 TEttinger: oh yeah

23:31 I don't know how you'd do it easily with non-binary numbers

23:32 justin_smith: replace bit-and and bit-shift-right with ? and logbaseN

23:54 ben_vulpes: does anyone have any tips on destructuring maps that use strings as their keys?

23:54 justin_smith: ben_vulpes: :strs

23:54 amalloy: ben_vulpes: do you know what {:keys [x]} is shorthand for?

23:54 ben_vulpes: amalloy: no sir

23:55 amalloy: it is short for {x :x}

23:55 justin_smith: ,(let [{:strs [a b c]} {"a" 1 "b" 2 "c" 3}] (+ a b c))

23:55 amalloy: so, you could write {x "x"}

23:55 clojurebot: 6

23:55 amalloy: as justin_smith shows, there is shorthand for that too

23:55 ben_vulpes: amalloy well yes, in that sense i am rather familiar with it.

23:55 the keys/strs switch is precisely the thing i b'leev.

23:55 where is that documented?

23:56 justin_smith: ben_vulpes: with the docs for destrucuring

23:56 * ben_vulpes has found, thank you

23:57 justin_smith: ben_vulpes: http://clojure.org/special_forms#Special Forms--Binding Forms (Destructuring)

23:57 oh man somebody should have put %20s in that string

23:57 those docs don't mention :syms or :strs though

23:58 oh, wait, yes it does

23:59 ben_vulpes: there's even a link to those docs in the doc string for let

Logging service provided by n01se.net