#clojure log - Feb 04 2016

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

0:31 Tilk: hello

0:40 hammer: hey there

0:41 any tips for newbies?

0:42 hello?

0:42 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline hammer

1:00 lambda-11235: hello?

1:00 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline lambda-11235

1:01 lambda-11235: What's fRaUline?

1:58 kenrestivo: german for "miss"?

7:57 dysfun: what are my alternatives to core.async in clojurescript if i want something with a very light footprint and i simply want channels and none of the async stuff?

7:57 justin_smith: dysfun: totally locking up because you have no threads

7:58 dysfun: lol

7:58 justin_smith: dysfun: more seriously, promises and callbacks? kind of sucks though

7:58 but you won't get channels

7:58 dysfun: *sigh*

7:58 are there any more light footprint options?

7:59 (i don't want a huge js file out of the other end)

8:00 justin_smith: probably not in cljs, but you might have luck with js-csp or something, there's a few libs that seem to try to do this, but I don't have a size comparison

8:00 * dysfun will probably figure something out

8:03 * dysfun has evil ideas involving web workers

8:05 dysfun: gosh, the only current browser they don't work in is opera mini

8:05 * dysfun considers implementing agents for cljs with web workers

8:06 justin_smith: that sounds interesting, and agents implicitly have queues that are effectively channels, so there you go!

8:07 dysfun: that was what i was thinking

8:07 there's a sort of odd similarity between actors and agents

8:08 justin_smith: agents are inside out actors

8:08 all the logic is always on the outside, passed in

8:13 dysfun: i think a channel can be accomplished with a persistentqueue and an atom

8:14 justin_smith: swap! retries and agents lock instead of retrying, so I wouldn't use an atom

8:15 well, maybe retrying on the queue operation is OK

8:26 dysfun: justin_smith: for a channel, not an agent

8:26 justin_smith: dysfun: the tricky thing with using an atom for a channel is you want a single op that returns the top item while removing it

8:27 dysfun: you'll find a pair of refs handles this much more cleanly

8:27 dysfun: great. thanks.

8:27 now i just have to write an stm

8:27 justin_smith: actually just one ref, but you need a transaction that alters the channel while removing the next item (for reads)

8:28 dysfun: not helping

8:28 justin_smith: well given the lack of threads you don't even need an atom

8:28 just punch the state in the gut and accept what you get

8:28 dysfun: yes, but atoms are sensible primitives

8:28 and obviously they're quite fast

8:29 justin_smith: given the absence of threads, what do they do for you?

8:29 dysfun: they provide a nice convenient interface over immutable data

10:22 Glenjamin: you still need somewhere to mutate, and cljs doesn't have vars

10:41 jsabeaudry: Let's say I want to (swap! a assoc :b :c) (swap! a update :d conj :e), would the clean way to write this be: (swap! a #(-> % (assoc :b :c) (update :d conj :e))) ? Is there a cleaner way?

10:50 justin_smith: Glenjamin: sure, but I also find it funny cljs has atoms but no vars

11:56 engblom: I am curious of why Clojure is faster when run with 'lein run' rather than 'java -jar whatever-standalone.jar'?

11:56 I am using (time ....) to measure, so the loading is not taking into account.

11:56 not need to be taken*

11:59 justin_smith: the java -jar version doesn't have hotspot turned on, hotspot has short term costs (the price of gathering the metrics and calculating optimizations) that are balanced by the optimizations it brings in later

11:59 err, I mean the lein version has hotspot turned off

12:00 so it could be a difference caused by hotspot getting ready to optimize (or even optimizing) but not doing enough yet for you to see the difference

12:00 engblom: Thanks! That explains

12:00 I will check my simple benchmark with a bit bigger loop

12:01 justin_smith: engblom: this could explain it - if you use (criterium.core/bench ...) instead of (time ...) you'll get a better answer

12:01 criterium is good at making sure hotspot has kicked in (if it can)

12:08 phillord: I found several orders of magnitude difference between criterium and time

12:08 engblom: Java HotSpot(TM) Client VM warning: TieredCompilation is disabled in this release.

12:08 So the hotspot is never used for me...

12:08 justin_smith: engblom: right, lein did that

12:08 java -jar won't give you that message

12:08 phillord: benchmarking well is very hard -- in general, you need to launch multiple times, with randomisation. Unless it's really really vital, I wouldn't bother.

12:08 justin_smith: so the java -jar gets optimized, lein run does not

12:10 phillord: what's wrong with using criterium with representative inputs? the reason it's different from time is because it's avoiding a bunch of noise sources that time is prone to

12:11 phillord: justin_smith: nothing wrong with it, just saying that the results you get might not reflect what happens outside of criterium

12:11 justin_smith: phillord: I'd say contrarywise that time doesn't reflect the results of the thing you are supposedly timing

12:11 dysfun: justin_smith: so i ended up using compare-and-set!

12:12 justin_smith: dysfun: ah, that sounds right

12:12 engblom: phillord: I am trying to understand so I could be able to get the raspberry pi gpio library a bit faster. Currently it runs at about 42kHz if you do nothing else than turning on and off a led. Compare it to this: http://codeandlife.com/2015/03/25/raspberry-pi-2-vs-1-gpio-benchmark/

12:12 phillord: The only thing slower is shell...

12:13 justin_smith: engblom: oh, another gotcha here is that the ARM jvm is hardly optimized compared to the x86 jvm

12:14 so you'd want to be sure any benchmarking is happening on the ARM device

12:14 engblom: justin_smith: I am doing all the benchmarking at the rpi2

12:14 justin_smith: cool

12:15 phillord: engblom: your running clojure on a PI? What's your boot time?

12:15 justin_smith: phillord: in my experience it's within usability ranges as long as you don't use lein - under 10 seconds

12:15 with lein it's insane and useless

12:16 minute long startups

12:16 phillord: justin_smith: I'm surprised -- I just assumed it would be awful and never tried

12:16 justin_smith: clojure is remarkably snappy when you get the tooling out of the way

12:17 engblom: phillord: I measured time to get a repl: 1m 6s

12:17 justin_smith: still a slow tool, but not like c++ compiler slow

12:17 dysfun: huh, does & not work in protocols?

12:17 or is there something special about a function called >! ?

12:18 phillord: engblom: not so bad -- about the same as my netbook

12:18 justin_smith: definitely nothing special about >!

12:18 engblom: phillord: It is fully acceptable as I anyway do not need to restart the repl during development. I send everything over with vim fireplace...

12:19 dysfun: clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: No single method: _GT__BANG_ of interface: irresponsible.baud.LineProto found for function: >! of protocol: LineProto, compiling:(/var/folders/k6/glc05svd5d194k8kgqfwkrph0000gn/T/boot.user9054690600505278700.clj:1:1)

12:19 phillord: engblom: learn something every day!

12:19 dysfun: https://gist.github.com/jjl/3b7f4ed3bd41f8c10079

12:19 engblom: phillord: This is my library (the first I ever made in clojure): https://github.com/engblom/gpio

12:21 justin_smith: dysfun: I'm getting "no single method" no matter how I try to use & in protocol method arg lists

12:21 dysfun: well that's quite irritating

12:21 justin_smith: dysfun: haha, time to do a clojure.core (defprotocol ITedious (foo [this]) (foo [this that]) (foo [this that other]) ....)

12:22 phillord: I might well give that a go, looks like fun

12:22 dysfun: justin_smith: hrm, do you not have to implement all of a protocol then?

12:22 justin_smith: dysfun: there is no requirement that one implement every method on a protocol

12:22 dysfun: of course you get a runtime error if you call one that was not implemented

12:22 dysfun: i think i can use that

12:23 justin_smith: this goes for Interfaces too in clojure (unlike javac)

12:25 engblom: phillord: By the way, if you ever run Clojure on RPI2, make sure you use oracle-jdk. Openjdk will take more than 7 minutes for repl and is unstandable slow on arm.

12:26 phillord: ah, that's interesting

12:26 engblom: Openjdk lacks JIT

12:26 kwladyka: justin_smith i back to "old" topic.... http://clojure.github.io/tools.logging/#clojure.tools.logging.impl/get-logger so (get-logger (find-factory) logger-ns) <- how is it works? get-logger i understand get implementation of Factory by namespace... but how is it works? Each namespace can have another Logger? How can i know Logger for third party module then?

12:26 engblom: JIT for arm

12:26 justin_smith: engblom: the default PI os for rpiII is oracle iirc

12:26 phillord: I'd heard that overtone has a 6-7 min boot time on PI, but that was a while back. Maybe this is why.

12:27 engblom: Probably. OpenJDK is running in interpreted mode on ARM, while Oracle-JDK is able to use JIT.

12:27 justin_smith: kwladyka: for java logging, loggers are configured per class

12:27 kwladyka: java doesn't even have namespaces

12:28 kwladyka: this is why the solution I was trying to encourage you to use was pure interop - because the java stuff isn't using the clojure.tools.logging.impl stuff

12:31 kwladyka: justin_smith not sure if i understand. Clear Java solution (LoggerFactory/getLogger Logger/ROOT_LOGGER_NAME) doesn't need namespace, but Clojure solution use namespace?

12:34 please correct me if i dont understand: this solution http://stackoverflow.com/questions/13760095/java-dynamically-change-logging-level turn off logging for all handlers where handlers are... namespaces? They use empty string here Logger.getLogger( "" )

12:36 rhg135: 20s to run nil on rpi1 with openjdk, hmm

12:37 kwladyka: justin_smith or maybe do you know site where i can clearly understand that? :)

12:38 engblom: rhg135: If you have a rpi1, could you please benchmark my gpio library? I would want to know if it is usable on rpi1. I can paste quickly somewhere some code for you to test.

12:39 rhg135: Yeah, engblom, that's fine.

12:39 engblom: rhg135: http://pastebin.com/dTKKDcKc

12:40 rhg135: That would turn on and off a led 1 000 000 times as fast as possible.

12:42 rhg135: With criterium? If so, idk if it'll be done today

12:44 engblom: rhg135: For me it is already enough if you run that program exactly as it is without criterium. That will already tell if it is usable

12:44 rhg135: and I don't need anything on the gpio port?

12:45 engblom: rhg135: no, you do not need anything

12:45 justin_smith: kwladyka: had a meeting, back now

12:46 kwladyka: justin_smith sorry if my question or not on high level. Just for some reason it confuse me.

12:46 justin_smith: kwladyka: clojure.tools.logger has per-namespace config for logging, java logging has per package and class configs. But you can get the "root" which they all default to.

12:46 rhg135: Cool, I will go run that

12:47 justin_smith: kwladyka: jvm logging is a mess, sorry.

12:47 kwladyka: justin_smith oh now it is more clear

12:47 justin_smith: OK

12:47 kwladyka: justin_smith so it is impossible to log off flyway using clojure.tools.logger ?

12:48 justin_smith: kwladyka: if you just want to set verbosity for java logging, you can use a logging.properties file for whichever logging backend is being used (there are a few out there)

12:49 kwladyka: clojure.tools.logger is just a set of macros for using the java logging from clojure

12:50 if you set up clojure.tools.logger to control the same logging subsystem that flyway is using, then you could use clojure.tools.logging to control flyway's verbosity

12:50 but to me it seems easier to just configure the logger flyway is using directly

12:50 either with a properties file if you want to set it statically, or the code I shared before for altering the level at runtime

12:52 kwladyka: (:import org.slf4j.LoggerFactory) (ch.qos.logback.classic Logger Level)) (.setLevel (LoggerFactory/getLogger Logger/ROOT_LOGGER_NAME) Level/WARN))) <- like that?

12:52 mpenet: "clojure.tools.logging" :>

12:52 justin_smith: yup, where WARN could be ERROR or whatever if you chose

12:52 mpenet: yes, right, he started it

12:52 haha

12:53 kwladyka: justin_smith ok so the question is... how can i be sure flyway will use exactly slf4j?

12:54 and how to set this only for block of code

12:56 justin_smith: slf4j is an abstraction layer over a few different loggers

12:56 kwladyka: justin_smith oh is it like clojure.tools.logging?

12:56 but for Java

12:57 and how can i set this only for block of code in tests? i don't want turn off logging for everything

12:57 only for flyway reset database

12:58 justin_smith: clojure.tools.logging is a wrapper over slf4j, commons-logging, log4j, java.util.logging, slf4j is a wrapper over log4j and java.util.logging and the whole world of java logging is so messy it makes me angry

12:58 jweiss: i was given this code to create a sorted set of ranges, like #{[1 2] [4 5] [6 7]}, but it's buggy: (apply sorted-set-by (fn [[from-a to-a] [from-b to-b]] (< to-a (dec from-b))) rs)

12:58 justin_smith: kwladyka: that code snippet doesn't turn the logging off, it just adjusts the level of logging, you can change it back afterward

12:59 jweiss: not sure what the issue is, i don't know what a comparator is supposed to do. i thought it returns an int, not just true or false?

12:59 justin_smith: jweiss: you don't need sorted-set-by, sorted-set will handle vectors just fine

13:00 jweiss: justin_smith: ok, just for my edification, is that comparator bad or is that how it's supposed to be?

13:00 justin_smith: ,(instance? java.util.Comparator >)

13:00 clojurebot: true

13:01 mpenet: kwladyka: you can silence it via a log4j.properties file

13:01 justin_smith: mpenet: he wants it only in one block of code

13:01 mpenet: just add en entry where it logs only "error"

13:01 ah

13:01 justin_smith: which is why the thing with Logger/ROOT_LOGGER_NAME etc. the little interop with ch.qos

13:02 ,(.compare > 1 2)

13:02 clojurebot: 1

13:02 justin_smith: ,(.compare < 1 2)

13:02 clojurebot: -1

13:02 justin_smith: jweiss: maybe that helps? ^

13:03 jweiss: sorted-set-by is going to use the function provided as its comparator, and call compare

13:03 jweiss: justin_smith: yep, thanks. i don't exactly see what's wrong with the code above, but i'll try just plain sorted set

13:04 justin_smith: jweiss: yeah, sorted-set should work, because compare already knows how to sort two element vectors

13:04 ,(sorted-set [6 7] [1 2] [4 5] [3 4])

13:04 clojurebot: #{[1 2] [3 4] [4 5] [6 7]}

13:07 justin_smith: jweiss: fun thing is that all clojure functions implement comparator

13:07 ,(.compare list 1 2)

13:07 clojurebot: #error {\n :cause "clojure.lang.PersistentList cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentList cannot be cast to java.lang.Number"\n :at [clojure.lang.AFunction compare "AFunction.java" 56]}]\n :trace\n [[clojure.lang.AFunction compare "AFunction.java" 56]\n [sun.reflect.NativeMethodAccessorImpl invoke0 "NativeMethodAcc...

13:07 justin_smith: oops!

13:07 doesn't always work

13:07 ,(.compare (constantly true) 1 2)

13:07 clojurebot: -1

13:07 jweiss: justin_smith: using sorted set doesn't behave correctly with the function I have that will combine ranges: like (add-interval #{[1 2] [4 5]} [3 3]) should be #{[1 5]}

13:08 then again, the sorted-set-by didn't work right either, but worked better :)

13:08 justin_smith: jweiss: you want the sorting operator to accomplish that?

13:08 jweiss: the sorting operator can decide which items are redundant, and where to put the ones that remain, but it cannot alter any of the values in the coll

13:09 maybe you want a new custom collection type instead

13:09 jweiss: justin_smith: right the other function i have would disj from the set and then conj a new item

13:10 justin_smith: jweiss: OK, but the sorting function can only order things, and decide on a pair by pair basis if things are >, <, or =

13:10 it can't merge things or eliminate based on a three way comparison

13:10 because .compare is called on two items at a time

13:10 jweiss: justin_smith: the other function call subseq, eg (subseq ranges <= [from from] <= [to to]) which i also don't quite understand how that works

13:11 justin_smith: OK, the sorted-set should give you [1 2] [3 3] [4 5] in that order, your code has to decide what it can merge

13:12 and that ordering is perfect for merging via reduce

13:13 jweiss: yeah good point, i don't understand how the function i was given works but i see how to do it with reduce

13:17 justin_smith: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [3 3] [3 5]])

13:17 clojurebot: [[1 5]]

13:18 justin_smith: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [3 3] [3 5] [7 10] [9 20] [420 666]])

13:18 clojurebot: [[1 5] [7 20] [420 666]]

13:18 jweiss: excellent, thanks

13:18 (inc justin_smith)

13:18 justin_smith: sadly lazybot is not with us

13:28 kwladyka: justin_smith logger factory depend on system where app is run?

13:47 jweiss: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges

13:47 el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [4 5] [7 9] [8 8]])

13:47 ugh

13:47 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

13:47 jweiss: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [4 5] [7 9] [8 8]])

13:47 clojurebot: [[1 3] [4 5] [7 8]]

13:48 jweiss: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 3] [4 5] [7 9] [6 6]])

13:48 clojurebot: [[1 3] [4 5] [7 6]]

13:48 justin_smith: jweiss: yeah, the reduce fails if the items are not sorted

13:48 jweiss: ah right

13:48 amoe: I would like to get pretty-printed output like 'pprint' from clojure.tools.logging and also use a format string like 'logf', and not have to explicitly pretty-print in every call, and also avoid premature evaluation of the pretty-printing depending on the log level. Any way to achieve this?

13:49 justin_smith: jweiss: you'd also see issues if any of the ranges were sorted wrong

13:49 or if they contained things not numbers

13:49 jweiss: justin_smith: right, i can guarantee the ranges will be correct

13:50 justin_smith: amoe: sounds like a cool logging lib you're about to implement

13:50 amoe: justin_smith: I thought so :)

13:51 I think maybe I can use this to help out https://github.com/AvisoNovate/pretty/blob/master/src/io/aviso/logging.clj

13:52 Will check into this tomorrow, I think

14:00 jweiss: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[3 3]] [[1 2] [4 5]])

14:00 clojurebot: [[3 2] [4 5]]

14:01 justin_smith: jweiss: the init should be [[i i]] where i is the lower bound of the first range

14:01 easy enough to set up in a function, of course

14:01 jweiss: justin_smith: i see

14:02 so i really want to conj the new range onto the sorted set, i thought the initializer was the item i'm adding

14:03 justin_smith: oh no, no, this reduce only does the combining, none of the sorting

14:03 I mean you could fix it to do the insertion, but that would be different

14:03 jweiss: wouldn't i just call sorted-set at the end?

14:04 justin_smith: but yeah, basically put the item into the sorted list or set of ranges, then do the reduce to combine apropriately

14:04 jweiss: i see thanks

14:04 justin_smith: and maybe put back into a sorted set again when it's done even

14:05 sadly you can't peek or pop sorted-sets, if you could that would simplify the whole thing

14:06 jweiss: right, will have to vec it and then turn it back to a sorted set. fortunately these lists will never be very long

14:06 justin_smith: well, the reduce can use a sorted-set

14:06 since they are at least seq-able

14:15 jweiss: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start e) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 2] [3 3] [4 5]])

14:15 clojurebot: [[1 2] [3 3] [4 5]]

14:15 jweiss: justin_smith: i'm still missing something here

14:16 justin_smith: what's missing?

14:16 jweiss: isn't that supposed to combine the ranges into [[1 5]]?

14:17 justin_smith: ahh, then you need to chang (> start e) to (> start (inc e))

14:17 I think that should do it

14:17 jweiss: ,(reduce (fn [ranges [start end :as el]] (let [[s e] (peek ranges)] (if (> start (inc e)) (conj ranges el) (conj (pop ranges) [s end])))) [[1 1]] [[1 2] [3 3] [4 5]])

14:17 clojurebot: [[1 5]]

14:17 jweiss: sweet

14:57 rhg136: and remember kids, don't hold on to the head of a seq

14:57 * rhg136 crashed his server due to an OOM

15:17 spuz: i have a long running process that reads from a lazy sequence

15:17 is it possible to log or print whenever a new item is read from that sequence?

15:17 dysfun: no

15:18 there are ways to achieve a similar mechanism, but there is no automatic hook for reading

15:20 spuz: I was just looking for a way to adapt my existing lazy sequence

15:20 and I think this will work: http://stackoverflow.com/questions/24597228/how-to-observe-progress-while-consuming-a-lazy-sequence

15:34 macrolicious: why does (def x 0) (let [x (inc x)] x) => 1 ? I would think it would produce => 0

15:36 dysfun: because a local binding shadows a namespace binding

15:36 it's why you can't write a function with a parameter 'list' and then use the 'list' function inside it without messing about

15:40 rotcev: is there a way to 'name' y and ys as a single parameter in clojure or do i just need to do (cons y ys) to join them where i need it [[x & [y & ys]]]

15:41 dysfun: [y & ys :as all-ys]

15:42 rotcev: ty dysfun

15:42 rhg135: ,(let [[a b :as c] [1 2 3]] [a b c])

15:42 where did clojurebot go

15:43 dysfun: well trust me, it works

15:43 even if clojurebot has gone off on one

15:45 justin_smith: ,(let [[a b :as c] [1 2 3]] [a b c])

15:45 clojurebot: ?

15:45 dysfun: i thought we had a backup bot for emergencies like this?

15:45 but i cant remember what the magic incantation to invoke it is

15:46 rhg135: clojurebot was the backup afaik

15:46 dysfun: oh. right.

15:48 macrolicious: I can be the bot for now.

15:51 dj broken bot in the house

15:52 rhg135: this is tragic

15:53 macrolicious: => Emilio Lizardo. Wasn't he on TV once?

16:12 WorldsEndless: Why doesn't this work? (-> "text" #(println %))

16:14 justin_smith: WorldsEndless: macroexpand-1 will tell you

16:14 WorldsEndless: But it doesn't....

16:14 justin_smith: ,(macroexpand-1 '(-> "text" #(println %)))

16:14 clojurebot: (fn* "text" [p1__25#] (println p1__25#))

16:14 justin_smith: that's what -> is doing

16:14 WorldsEndless: ? Mine gives me a Runtime Exception

16:14 oh, the quote

16:14 justin_smith: you need to quote forms in order to macroexpand

16:14 yeah

16:15 so you see, #() expands to a call to fn, then "text" becomes the first arg to fn

16:15 WorldsEndless: what's the p1_25# business?

16:15 justin_smith: ,'#(foo)

16:15 clojurebot: (fn* [] (foo))

16:15 justin_smith: ,'#(foo %)

16:15 clojurebot: (fn* [p1__74#] (foo p1__74#))

16:16 justin_smith: it's a random parameter name that won't clash with anything else

16:16 (in fact generated in a way that ensures it can't possibly clash)

16:17 WorldsEndless: so, am I reading this right that "text" becomes the name of teh function, not a parameter?

16:17 spuz: woot. i got my sudoku algorithm down from over an hour to under a second

16:18 AimHere: Was the hour one just brute force?

16:18 spuz: they are both just brute force ;)

16:19 WorldsEndless: spuz: added threading?

16:19 spuz: nope

16:19 just must simpler and smarter validity checking

16:19 butters: I want to create a GUI app and am currently deciding on clojurescript and reagent. Is there something else that would be a better experience?

16:19 spuz: before I was creating a grid (vector of vectors) and then checking if that grid was valid

16:20 now I am simply picking a cell, and checking if the values 1-9 already exist in the rows/columns/squares that intersect it

16:20 i.e. no datastructure manipulation

16:21 actually, there is a bit of vector creation to get the columns and squares but somehow it's still pretty speedy

16:21 WorldsEndless: butters: I'm rather a fan of reagent/clojurescript

16:42 spuz: oh man, actually I found a really really stupid bug in my original implementation. I mixed up the x and the y coordinates which meant it was checking the wrong cells for validity

16:42 with that fixed, the original solution is almost as fast as the new onw

16:44 i guess this is why we write tests

17:10 xemdetia: maybe

17:13 dysfun: what's the go-to for reading edn in cljs?

17:15 justin_smith: dysfun: cljs.reader/read-string

17:16 devth: best way to get a range of items in the middle of a lazy seq? repeatedly call nth?

17:16 dysfun: justin_smith: ta

17:17 amalloy: devth: drop + take?

17:17 devth: amalloy: thx. it's a line seq. i wonder if nth would be any worse?

17:17 amalloy: a lot worse, if i understand your question

17:18 devth: i don't know whether or not line-seq is indexed

17:18 amalloy: no

17:18 and even if it were that wouldn't help

17:18 devth: got it. ty

17:18 justin_smith: lazy-seqs are never indexed

17:18 devth: i guess that makes sense

17:20 so every time you call nth it's iterating from the beginning, and forcing any unrealized values along the way

17:22 justin_smith: well, "along the way" sounds open ended, but lazy seqs are always realized in order, but yeah

17:24 phorse: Is there a document anywhere that talks about project.clj? I'm getting confused about profiles vs builds and where dependencies belong and how you configure them.

17:24 justin_smith: phorse: lein help example

17:25 also findable via google if you search for "leiningen sample project.clj"

17:25 phorse: oh, sorry, it's

17:25 "lein help sample"

17:26 phorse: Wow, this is a gem!

17:26 This should be more widely advertised, I think.

17:26 justin_smith: phorse: there are few things lein can do without a plugin that are not documented there

17:27 phorse: I might ask some more questions once I've read this, then, because I'm deep in the plugin weeds right now - mainly with figwheel but also with others.

17:28 justin_smith: plugins can do "anything" but typically either define a dev utility task launched by lein, or transform your deps somehow

17:33 phorse: So, plugins can specify their own keys and configuration in the project.clj, right?

17:34 justin_smith: phorse: they can ingest the whole project file and it's up to them which part they use and how

17:34 yeah

17:34 phorse: And these can all be profile specific, as configured under the :profiles key?

17:34 justin_smith: right, or they can be top level keys in the profile

17:34 depends on the plugin and how it is being used

17:35 phorse: Ok, I think that makes sens.

17:36 Do you use environ? Do the keys in profiles.clj correspond with the profile ids in :profiles in project.clj?

17:37 justin_smith: yes and yes

17:37 well wait, now

17:37 yes

17:37 phorse: ok!

17:38 justin_smith: environ lets me put less essential credentials for dev time in the project file, and prod configs in the env map on the server

17:38 s/less essential/less vulnerable/

17:38 eg. password to a server that doesn't even have access from the net

17:40 phorse: So, in the case of a database connection, if I want to use one connection while in dev, but when I build an uberjar for prod use another database connection, I could specify that in the profiles.clj

17:41 justin_smith: well, in prod you wouldn't have a profiles .clj would you?

17:41 in prod environ can read from an environment variable from the system

17:41 phorse: No, but doesn't it merge the maps when uberjarring?

17:42 justin_smith: phorse: none of those profiles are available at deployment unless you seek them out and parse them by hand, they are build time / dev time config

17:42 phorse: Ahh, I was confused then.

17:42 justin_smith: lein stuff is not for app config, it is for build config (but there is definitely a tendency to try to scope creep there...)

17:43 but fundamentally it's a build tool

17:43 phorse: this is actually why environ is good - it can find a value in project.clj, in a java system property, or a shell environment variable, and your code will look the same

17:43 it just looks until it finds one

17:44 phorse: I'll have to play around with it - that could really simplify our process

17:44 rhg135: it's funny how short and simple the code is

17:45 justin_smith: rhg135: yeah, kind of hilarious actually - it takes more characters to explain how to use it and why it is useful than it takes to implement it

17:45 rhg135: indeed.

17:46 like most of the seq functions without optimization

18:35 WorldsEndless: I'm trying to specify the separator for a data.csv output to be a tab char, but it can't receive strings. How do I specify a tab char, since \t is a plain "t"?

18:39 ToxicFrog: WorldsEndless: \tab or \u0009

18:39 WorldsEndless: http://clojure.org/reference/reader#_literals

18:39 WorldsEndless: Ah! Thanks!

19:14 justin_smith: ,(first "\tanother method")

19:14 clojurebot: \tab

19:16 justin_smith: ,(iterate pr-str "\\")

19:16 clojurebot: ("\\" "\"\\\\\"" "\"\\\"\\\\\\\\\\\"\"" "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\"\\\"\"" "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"" ...)

19:17 justin_smith: wow, that blows up fast

19:17 ,(drop 5 (iterate pr-str "\\"))

19:17 clojurebot: ("\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"" "\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\...

19:19 amalloy: should be exponential, right

19:19 justin_smith: yeah, I guess so

19:20 ,(map count (iterate pr-str "\\"))

19:20 clojurebot: (1 4 10 22 46 ...)

19:20 justin_smith: ,(map count (drop 5 (iterate pr-str "\\")))

19:20 clojurebot: (94 190 382 766 1534 ...)

19:26 Glenjamin: ,(map count (drop 5 (iterate pr-str "\\\"")))

19:26 clojurebot: (126 254 510 1022 2046 ...)

19:27 Glenjamin: that didn't have as much of an impact as i'd have hoped

19:27 justin_smith: powers of 2 - 2 !

19:28 while mine is a little less clear

19:28 Glenjamin: exponential growth!

19:28 yours is x2 + 2

19:29 oh, they both are

19:29 just different start point

19:31 justin_smith: Glenjamin: yours is (2^n)-2, but I'm not seeing the formula for mine

19:32 Glenjamin: hrm, i need a repl

19:32 or a spreadsheet

19:35 justin_smith: ,(def n (map count (iterate pr-str "\\")))

19:35 clojurebot: #'sandbox/n

19:35 justin_smith: ,(map - (rest n) n)

19:35 clojurebot: (3 6 12 24 48 ...)

19:35 justin_smith: so we have a series of doubled differences

19:35 ,n

19:35 clojurebot: (1 4 10 22 46 ...)

19:36 Glenjamin: n1 = n0 * 2 + 2

19:36 justin_smith: yeah, sounds right

19:36 Glenjamin: i've forgotten the maths to turn that into a function of i

20:33 hxegon: Trying to get node-host working with neovim for paraedit. Anyone know why I wouldn't have a bundle/node-host folder after :PluginInstall?

20:36 nevermind... had a .vim folder and it was going off of that

20:48 Somelauw: In Python I would create a startup file .pythonrc that contains lines like import re, import math, etc to have them immediately available when I start a repl. How would I achieve something similar in Clojure?

21:00 rhg135: The python repl is a lie! But AFAIK clojure does none of that magic

21:01 Well, it will load user.clj on the classpath

21:24 lockdown: Somelauw: create an namespace with the ns macro and put what you need there, then in the repl switch to that nswith in-ns

21:34 Somelauw: lockdown: that's what I'm doing

21:52 kenrestivo: is there any guarantee of the order that tests are run with clojure.test?

21:52 reason being: i'm seeing on one machine, foo.bar-test is being run first, on another machine foo.baz-test is being run first

21:56 rhg135: I think the runner uses a map, but I may be wrong

22:01 kenrestivo: thanks, that'd make sense. key order not guaranteed.

22:59 cortexman: teach me something about clojure

Logging service provided by n01se.net