#clojure log - Jun 27 2014

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

0:00 dbasch: if anything, the point of fnil is to recover from null pointers and avoid a null pointer exception

0:00 boltR: ah I see

0:01 I was trying to create an anonymous function for passing to update-in

0:02 I think I can just use an if-else

0:02 dbasch: you want to throw an exception in the middle of an update?

0:02 boltR: yeah if a key doesn't already exist in the hashmap

0:05 dbasch: boltR: update-in will create them if they don't, so you'd have to check

0:07 e.g.

0:07 ,(update-in {:a {:b 1}} [:a :c] str)

0:07 clojurebot: {:a {:c "", :b 1}}

0:14 boltR: dbasch: ah I see

0:14 so I need to check the hash before the update-in call

0:19 trptcolin: ,(update-in {:a {:b 1}} [:a :b] #(if % (inc %) (throw (Exception. "this is bad code"))))

0:19 clojurebot: {:a {:b 2}}

0:19 trptcolin: ,(update-in {:a {:b 1}} [:a :c] #(if % (inc %) (throw (Exception. "this is bad code"))))

0:19 clojurebot: #<Exception java.lang.Exception: this is bad code>

0:26 boltR: trptcolin: why is that considered bad code?

0:29 trptcolin: don’t mind me, i’ve been watching monad videos

0:30 it works, just not a use case where i’d typically reach for exceptions

0:33 boltR: trptcolin: i just realized i'm not supposed to put the exception in the update-in line

0:33 haha

0:33 oh well.. still good to know

0:41 ndp: Hey all, what's the right way to compare keywords in ClojureScript?

0:41 Right now I'm using keyword-identical? but it's not working when getting a value from a map to compare against.

0:43 Ah, never mind - I found the problem as I was copying here. I had an extra ":" floating around.

0:52 ttasterisco: ,(= :k1 :k2)

0:52 clojurebot: false

0:52 ttasterisco: ,(let [x :k1] (= :k1 x))

0:52 clojurebot: true

0:53 ttasterisco: ,(doc keyword-identical?)

0:53 clojurebot: It's greek to me.

0:55 john2x: how do I upgrade my leiningen? I tried `lein upgrade`, but it seems it's intended for projects?

0:56 trptcolin: `lein upgrade` should work for the normal case. perhaps you have lein installed via a package manager?

0:56 what is the problem you’re seeing?

0:57 john2x: sorry, got disconnected. trptcolin, you mean me?

0:57 ttasterisco: yes

0:58 john2x: "Couldn't find project.clj, which is needed for upgrade"

0:58 ttasterisco: huh

0:58 john2x: It does update a bunch of libraries in my .lein/profiles.clj though

0:58 but I want to update to lein 2.4.x (currently on 2.3.4)

0:59 ttasterisco: I just updated my lein with lein upgrade

0:59 Leiningen 2.4.2 on Java 1.8.0_05 Java HotSpot(TM) 64-Bit Server VM

1:00 john2x: strange.. i installed this via homebrew.. but on brew it's still at 2.3.4.. and I don't want to use HEAD

1:00 I guess I should re-install from the github downloads?

1:00 ttasterisco: https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein

1:02 trptcolin: john2x: yeah `lein upgrade` doesn’t work for package managers unless they go in and tweak the script (which nobody does, i don’t think): https://github.com/technomancy/leiningen/issues/1377

1:03 john2x: thanks. oh and it seems it's at 2.4.2 in homebrew now.. guess I'll just keep on brewin'

1:05 ddellacosta: john2x: not sure but I think most folks avoid leiningen via homebrew. YMMV

1:06 john2x: hmm yeah.. probably would cause more hard-to-diagnose issues someday.

1:23 Raynes: john2x: It's just that leiningen is just a shell script and a jar file.

1:23 So using a package manager feels strange :P

2:58 Klaufir: how can I generate a vec using a function ?

2:58 I have tried

2:58 (reduce #(cons (rand 1) %1) [] (range 10))

2:59 but this is problematic because #(...) here takes only 1 argument

3:09 AimHere: Klaufir, what do you mean by 'generate a vec using a function'?

3:11 ,((fn [] (vec (range 10))))

3:11 clojurebot: [0 1 2 3 4 ...]

3:11 Klaufir: AimHere: call a function n times, then put the n results into a vec

3:11 AimHere: Oh, well that's outwith the functional idiom

3:12 Klaufir: AimHere: how would you generate a vec of random numbers?

3:12 given by the function 'rand'?

3:13 AimHere: (vec (take 10 (repeatedly rand)))

3:13 ,(vec (take 10 (repeatedly rand)))

3:13 clojurebot: [0.12962159592537548 0.31180927009168413 0.7594697727309286 0.7412669247226338 0.18135883841833167 ...]

3:13 AimHere: You should be thinking in terms of laziness and sequences in Clojure, for that sort of thing

3:14 You *could* write a reentrant function using atoms or refs as static variables, but it's unidiomatic

3:16 Klaufir: AimHere: thanks, this looks great

3:38 ddellacosta: ,(clojure-version)

3:38 clojurebot: eval service is offline

3:38 ddellacosta: damnit

3:38 &(clojure-version)

3:38 lazybot: ⇒ "1.4.0"

3:38 ddellacosta: &(name :/)

3:38 lazybot: java.lang.RuntimeException: Invalid token: :/

3:38 ddellacosta: &(name :-)

3:38 lazybot: ⇒ "-"

3:39 ddellacosta: &(name (keyword "/"))

3:39 lazybot: ⇒ "/"

3:39 ddellacosta: &(keyword "/")

3:39 lazybot: ⇒ :/

3:39 blur3d: Hey guys, I’m trying to make a way to visualise data collected in real-time from an Arduino. Basically, data comes in at unpredictable intervals (potentially 100,000 of data points). It could contain anolog inputs (0-1023) or digital inputs (0-1), as well as other data. So basically, I have lots of specific timeseries, and I was wondering hwo I should go about jumping back in time and getting the whole system state.

3:40 I’m fine with creating snapshots of data every second or something if that is required, and then that could be used to slide back in time to a past state

3:40 oh, and I am hoping to do this is clojurescript

3:41 ddellacosta: blur3d: I guess my first instinct would be to snapshot everything with the timestamp as the hashmap key, perhaps?

3:41 blur3d: in an atom

3:42 blur3d: depending on how the data looks you could diff the previous state and store that each time, or start with some default state and just store diffs, computing the state at any given point?

3:43 blur3d: Yeah, I’m just not sure how to keep as much resolution as possible in the data, and the history

3:43 because a value could update 100s of times a second

3:44 but more likely 100Hz would be plenty

3:44 ddellacosta: blur3d: ah, I see. Are the updates subsets of data, or do you get an entire snapshot?

3:45 blur3d: one idea is to use a counter and ignore updates unless you've hit a timeout/passed a threshold

3:45 blur3d: well, the arduino input would have no real relation to past data for 50% of the time

3:45 ddellacosta: blur3d: I see, so it's a snapshot of the entire system state? Sorry if I'm not getting it, never used an arduino

3:46 blur3d: well, the state that matters…. not all the microcontroller inputs/outputs might be being used

3:47 and they could just default to some initial state

3:47 http://icant.co.uk/talks/h5/pictures/smashingconf/shorterjourney.jpg

3:47 ddellacosta: blur3d: not sure what you mean by that image

3:48 blur3d: that is kind of the same problem I am trying to solve.. I’m just really new to it and haven’t found many OSS to peer at

3:48 see how the player state is snapshot over time… ie. you can see where he was and where he is going

3:48 Frozenlock: blur3d: could you describe what you want to accomplish by keeping all these samplings?

3:48 blur3d: in that case it is just x and y over time

3:49 Basically, lets say I have a temperature sensor I hook up to the arduino

3:49 ddellacosta: blur3d: well, the choice is simple it seems to me--you either keep an entire snapshot of state at a regular interval, or just updates to an initial state, which you compute on the fly if you need to go back in time

3:49 blur3d: it will give me back a temperature each microcontroller cycle (not at a set interval)

3:50 I want to read those values into a clojurescript app in real time and display visualisations on the current state

3:50 (obviously temperature is not important enough to read at 100Hz, but think of motors and such)

3:51 Frozenlock: Even with motors, I don't really see why 100hz... I mean, the human eye can't see that :-p

3:51 ddellacosta: blur3d: I mean, there are a ton of variables in here that you will need to fine-tune, but the heuristic seems pretty simple

3:51 blur3d: no, but it would change the speed and therefore effect distance travelled etc

3:52 ddellacosta: blur3d: obviously if you need to get something that is going to fool the eye, as Frozenlock says, it has to be fast enough--but doesn't need to be past 16 frames a second or something

3:52 whatever that is. 24? I forget

3:52 Frozenlock: 60 for a good FPS :-p

3:52 (first person shooter)

3:53 ddellacosta: blur3d: right; but that's why you take a snapshot at a regular interval regardless, and you make sure you can either compute the entire system's state, or it is all stored for that snapshot

3:53 blur3d: sure, I might use moving averages for the visualisations

3:53 but I was keen to somehow also keep mass data for playback/simulation later

3:53 yeah, ok.. I’ll give it a go

3:53 ddellacosta Frozenlock thanks

3:53 Frozenlock: blur3d: I'd store a snapshot of all the values every MCU cycle

3:54 ddellacosta: blur3d: I mean, I guess there is a tricky bit where you get something inside the threshold, if you are listening vs. polling

3:56 Frozenlock: (assuming you don't run it for an hour)

3:56 blur3d: yeah, I would just have to accept it may be lossy

3:56 ddellacosta: blur3d: yeah, but (say if it was an animation output) as long as you fooled the human eye it doesn't matter if the update came in at T150ms and you played it back at T155ms or whatever

3:56 blur3d: anyways, good luck, hope this helped at least to think through it

3:56 blur3d: yeah, I have a better idea now… Thanks again

3:56 Frozenlock: I remember programming MCUs in C... without a repl...

3:56 Terrible, terrible times.

3:56 * ddellacosta pats Frozenlock on the back in consolation

3:57 * Frozenlock starts crying and hugs ddellacosta

3:58 ddellacosta: haha

3:58 blur3d: The Arduino IDE doesn’t have a repl yet, haha

3:59 ddellacosta: yeah, I vaguely remember doing a bit of that sort of thing, writing stuff into a terrible proprietary editor and then pushing it to the microcontroller

3:59 I guess Arduino is better than that

4:02 blur3d: This is the general idea of what I am working on http://vimeo.com/97903574 (15 min video). Basically a real-time dashboard for what exactly the arduino is doing

4:04 Frozenlock: "You sit at your desk and look at this tiny rectangle" Pfff, my rectangle isn't tiny

4:16 blur3d: haha, he may of.. but he’s been doing similar stuff for a few years now

4:18 I’ll take a look… it sounds nice

4:18 and it seems fairly popular - I’ve never head of it

4:18 Frozenlock: If you do use crossfilter, you should really take a snapshot of all the values everytime.

4:20 blur3d: ok, well any value updates come in one at a time. I’ll work on getting the foundation setup, and then I’ll look at how much data I actually need/want

4:21 the difficulty is that I was hoping to let the users send data whenever they feel necessary… and that could be very often

4:21 but it may also be once a minute, or 10 minutes

5:22 blah: Why does my page display only Test2 in the following code ? http://bpaste.net/show/C6qQOHrUAwdHWgQbKS0J/

5:22 This is attempting to use om

5:38 Slotkenov: What might I be doing wrong when in the repl "(cemerick.austin.repls/browser-connected-repl-js)" works fine, but "(require [cemerick.austin.repls :refer [browser-connected-repl-js]])" returns the error "CompilerException java.lang.ClassNotFoundException: cemerick.austin.repls, compiling:(/tmp/form-init4786187161975553725.clj:1:1)"?

5:48 I forgot to quote in the require statement :)

5:54 jonathanj: how do i concisely write: if (f.foo() && f.bar()) { X } else { Y } in clojure?

6:02 Slotkenov: @jonathanj (if (and (foo) (bar)) X Y)

6:21 jonathanj: how do i give a typehint of an array of something? eg. Foo[]

6:27 TEttinger: jonathanj, ah that's a classic thing

6:27 there's a good post on it...

6:27 http://www.learningclojure.com/2010/09/macros-and-type-hints-metadata-and.html

6:28 clgv: jonathanj: for objects there is "^objects"

6:28 TEttinger: err, http://asymmetrical-view.com/2009/07/02/clojure-primitive-arrays.html

6:31 clgv: ,(-> (into-array Long/TYPE (range 3)) class ((juxt identity #(.getCanonicalName %))))

6:31 clojurebot: [[J "long[]"]

6:32 clgv: ,(-> (into-array Long/TYPE (range 3)) class ((juxt #(.getName %) #(.getCanonicalName %))))

6:32 clojurebot: ["[J" "long[]"]

6:35 jonathanj: thanks

6:58 hrm, so if i do: lein uberjar, i can't run the resulting jar as-is: Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/IFn

6:58 presumably i need some clojure stuff in my classpath but i'm not sure what or how

7:03 oh there is a separate standalone jar, my bad

7:21 ambrosebs: is it possible to extend an Object[] to a protocol?

7:22 VerifyError (class: clojure/core/typed/array$eval13206, method: invoke signature: ()Ljava/lang/Object;) Incompatible object argument for function call java.lang.Class.getDeclaredConstructors0 (Class.java:-2)

7:22 I seem to get that.

7:22 Integer[] seems to work.

7:25 clgv: ambrosebs: extend-protocol together with (java.lang.Class/forName "[Ljava.lang.Object;") worked

7:25 ambrosebs: ah, I tried extend-type with (class (object-array []))

7:26 weird that (class (make-array Integer 0)) worked for Integer[]

7:27 right, Class/forName still gives me the same error.

7:27 clgv: ambrosebs: again some core.typed "overload" like "fn" last time?

7:28 ambrosebs: clgv: most likely, I'll try somewhere else :P

7:29 clgv: I tried in an almost fresh repl ;)

7:29 jonathanj: hrm, is there a shorter way of writing (apply #(Foo. %1 %2 %3 %4) [12 34 56 78])

7:30 (in reality the args vector comes from splitting a string and is checked for exactly 4 arguments)

7:30 vmarcinko: hello, just wondering - if I increment some counter contained in plain clojure vector (integer element) a billion times, it will take significant amount of memory for this action since clojure's immutable structures don't upodate anything, but only add new data states in memory, (similar to Git)?

7:31 ambrosebs: clgv: https://gist.github.com/frenchy64/19e299d0c96524afc5d5

7:33 clgv: jonathanj: thats a record or deftype right? than there is (->Foo 12 34 56 78)

7:35 jonathanj: hmm?

7:36 it's a com.itext.text.Rectangle in this particular case

7:37 i ended up using vec destructuring and :as

7:43 clgv: jonathanj: well than not ;)

7:44 jonathanj: in case of deftype and defrecord you get that convenience function

7:47 ambrosebs: I'm on java7 fwiw.

7:47 I'll try clojure 1.6

7:47 clgv: ambrosebs: Clojure 1.6 on Java 7 here

7:48 ambrosebs: eh same error for me

7:48 weird!

7:48 razum2um: vmarcinko: see transient topic

7:48 vmarcinko: http://clojure.org/transients

7:49 clgv: ambrosebs: https://www.refheap.com/87610

7:50 vmarcinko: transient vector and assoc! should do the trick

7:51 razum2um: folks, is there any clojure online playgrounds like http://www.tryerlang.org/ ?

7:52 nathan7: razum2um: http://tryclj.com/

7:52 clgv: razum2um: http://tryclj.com/

7:52 :P

7:55 razum2um: oh, not correct example, i asked for http://www.jsfiddle.net/ more. you gave link to refheap, but what if i just want to fork&edit code on link above with instant feedback from repl

8:00 ambrosebs: clgv: huh, does (blubb (object-array 1)) work for you?

8:00 into-array works for me

8:00 razum2um: hm, realized that I thought about lighttable online + collaborative editing like gits

8:01 s/gits/gist/

8:01 clgv: ambrosebs: no it does not

8:01 ambrosebs: I have no idea why

8:03 ,(identical? (class (object-array 0)) (class (into-array Object [1 2])))

8:03 clojurebot: true

8:03 petrust: how do I include an unstable clojure dependency that is not on clojars? e.g. reagent 0.4.3 ?

8:04 vmarcinko: <razum2um>: thanx

8:04 razum2um: thanx

8:05 hyPiRion: petrust: git clone the repo, then perform `lein install` in its root directory

8:07 clgv: ambrosebs: thats pretty damn weird

8:07 razum2um: yep, such already exists but doesnt support clj - https://eval.in/

8:10 clgv: ambrosebs: ##(let [a1 (object-array [1 2]), a2 (into-array Object [1 2])] (println (identical? (class a1) (class a2)) (java.util.Arrays/equals a1 a2)))

8:10 lazybot: ⇒ true true nil

8:11 michaelr525: hello

8:14 ambrosebs: clgv: looks like into-array is created with reflection and object-array is created with java syntax.

8:14 the only difference I can see.

8:15 clgv: ambrosebs: should be the same though? "length" is in fact done via java.reflect.Array as well afaik

8:16 interesting mail topic for clojure-dev though ;)

8:16 ambrosebs: perhaps there's a subtle difference between Array.newInstance(Object, 1) and Object[1]

8:16 clojurebot: It's greek to me.

8:17 clgv: ambrosebs: wouldnt that even violate the java spec?

10:22 Klaufir: i need some help understanding dependency management in cider + lein

10:23 first, how do I download dependencies?

10:24 say I want 'data.json', and have the following line in project.clj

10:24 :dependencies [[org.clojure/clojure "1.6.0"] [org.clojure/data.json "0.2.5"]]

10:24 cbp: you declare them in your project.clj and lein will download them automatically if it needs to

10:24 after you do something like lein repl

10:24 Klaufir: I see

10:25 teslanick: You can force it by running `lein deps` on the command line

10:25 Klaufir: thanks

10:25 and how do I make sure these deps are available in the REPL after cider-jack-in ?

10:25 for example when editing core.clj, and have a project file with [org.clojure/data.json "0.2.5"] included

10:26 I can't seem to access the json functions

10:26 is cider-jack-in supposed to resolve dependencies using lein ?

10:28 cbp: cider-jack-in calls lein repl so yes

10:29 Klaufir: can you point me towards some useful documentation regarding dependency management in clojue ?

10:29 so far, its very unintuitive, confusing and buried behind lein magic

10:30 cbp: https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md

10:30 _Atom_: HELLO IS MY FRIEND HENRY HERE?

10:30 LOL

10:31 Klaufir: cbp: exactly what I was looking for, thank you :)

10:31 deathknight: what's this doing here

10:31 _Atom_: fgt shit

10:31 rplaca: Klaufir: I think you might be confusing the dependency management with accessing namespaces

10:32 Klaufir: if your project.clj is set up like you say, you should have the dependency available and you just need to do a require when you want to access it

10:33 e.g. at the repl: (require '[data.json :as json])

10:34 or in the ns form of your core.clj: (:require [data.json :as json])

10:37 Klaufir: rplaca: thanks :)

10:38 rplaca: Klaufir: hope that helps!

11:43 orend: hey, I have a midje question: is there a way to ask midje to load the test lein profile? I want to make sure it uses the test database, and I want to clear it before the tests

11:44 core.test is loading the test profile in lein, midje doesn't seem to do it

11:52 gfredericks: orend: `lein with-profile +test whatever-the-midje-task-is` will do it

11:52 and you can make an alias for that

12:17 dgleeson: does memoize have any memory impacts I should be considering before using it?

12:17 arrdem: dgleeson: memoize has an unbounded cache size..

12:18 ambrosebs: https://github.com/clojure/core.cache

12:18 arrdem: at least clojure.core/memoize does... core cache fixes that nicely.

12:18 Bronsa: there's also core.memoize that's built on top of core.cache and it's friendlier

12:19 dgleeson: interesting thanks!

13:02 mmitchell: anyone here use clj-logging-config for log configuration?

13:21 bbloom: Bronsa: symbol-macrolet was super easy to add & solves my problem quite nicely :-)

13:22 AeroNotix: Just been to EuroClojure. What's with the bruce meme?

13:24 seangrove: AeroNotix: What bruce meme?

13:25 * seangrove panics about falling behind in meme knowledge

13:26 AeroNotix: seangrove: a lot of talks contained a picture of a guy called "Bruce" with a goatee

13:30 https://skillsmatter.com/members/otfrom

13:30 oh this guy

13:31 arrdem: I'd bet he's an organizer and it was presenters screwing with him

14:10 amalloy: bbloom: what problem did symbol-macrolet solve? i'm always excited to hear about new uses of it

14:11 bbloom: amalloy: in eclj i didn't want to special case fields inside deftype method bodies. so i used symbol-macrolet to expand field names to (.-field this) style forms

14:12 amalloy: ah. sounds perfect, yep yep

14:12 Bronsa: bbloom: oh so it worked, cool

14:12 bbloom: Bronsa: yup: https://github.com/brandonbloom/eclj/commit/bb885d02079387c675065d3347754f4bb1e54e29

14:12 and https://github.com/brandonbloom/eclj/commit/d99ba8f2fe72b71d360e602f2c466faf03ec01ac

14:12 (deftype is still a slow as shit dirty hack, but i'm not worried about the perf of it until i get to the compiler)

14:13 going to generalize set! too... basically to CL's setf

14:13 Bronsa: woah

14:14 bbloom: that sounds fun but I'm not really sure if it would be really useful in clj given absence of pervasive mutability

14:14 bbloom: do you have specific use-cases for that or is it just something cool you want to implement?

14:17 bbloom: Bronsa: i need to rework my code for set! anyway to understand symbol macros & it's pretty easy to just make that a protocol... effectively providing setf

14:17 right now it's an if/else and will become a cond, so might as well make it a proto fn and call it done :-P

14:18 but i don't need field setting yet, so i'll cross that bridge when i come to it

14:19 i'm doing JIT development :-)

14:21 Bronsa: bbloom: ah yeah, I probably need to do something like that too

14:22 right now (set! foo bar) compiles to a setfield while (set! (.-foo this) bar) uses reflection IIRC

14:22 it should definitely be possible to make the latter compile to a setfield too

14:23 nevermind it already does.

14:23 Willis1: bbloom

15:28 catern: agh

15:28 Is there a "Java for Clojure developers" tutorial anywhere?

15:28 ndaly: haha

15:28 I thought the same thing

15:28 catern: I've never actually worked in Java before, so

15:31 mikerod: Is it safe to use (clojure.lang/RT/nextID) as a way of getting a unique identifier within a given JVM instance?

15:31 cbp: I recommend Java in Action which is probably as close as you can get

15:31 mikerod: I know this is used by `gensym`

15:31 but here, we don't actually need a symbol and do not want the overhead of creating one

15:32 catern: cbp: I really don't want to learn Java, though

15:32 (as the exposure I have had to it, even before Clojure, convinces me it is garbage)

15:32 ndaly: it is

15:33 catern: I come to Clojure from Lisp, not Java :)

15:33 cbp: I'm not sure how to help you learning something without learning it

15:34 ndaly: Rich Hickey's talks (on youtube) entitled Clojure for Java Programmers is a gentle way to get some indirect understanding of the Java you might want to know

15:34 while learning some interesting stuff about Clojure and it's implementation

15:34 mikerod: Rich Hickey also has a talk Clojure for Lisp programmers

15:34 ndaly: that one won't play past like minute 6 for me

15:34 which is killing me, cuz I really want to watch it

15:35 mikerod: https://www.youtube.com/watch?v=cPNkH-7PRTk

15:35 I've listened to both the Java and Lisp variety. The Lisp one is probably more insightful in my opinion. However, I'd think they both have value.

15:35 Not to mention the Lisp one does assume you know something about Lisp. However, this is what catern said he was from.

15:36 ndaly: yeah, that video dies at 6:35

15:36 mikerod: weird

15:37 I haven't tried

15:37 it used to work :P

15:39 dbasch: mikerod: I would use my own atom rather than rely on nextID

15:39 cbp: why not a uuid4 or something?

15:40 dbasch: cbp: he said he doesn't need uuids, only something unique within that jvm

15:41 Shayanjm: catern: why dive into java when you know clojure?

15:41 I would imagine you can accomplish the same thing(s), just without consistently shooting yourself in the foot

15:41 catern: Shayanjm: I don't want to dive into Java

15:41 dbasch: Shayanjm: because using Clojure properly requires knowing Java

15:41 to some extent, at least

15:41 Shayanjm: That's fair, but Java development is INCREDIBLY OO centric

15:42 keeping code DRY is an impossible feat

15:42 catern: Shayanjm: I want to lightly touch the surface of Java, while heavily insulated by Clojure's protective embrace

15:42 dbasch: Shayanjm: so? You don't need to code in java

15:42 Shayanjm: dbasch: I know - that's why I was asking why catern was asking about 'java for clojure devs'

15:42 catern: Shayanjm: also I only need to be able to read Java code, not write it. And occasionally run it

15:42 Shayanjm: if he wanted to actually -learn- java

15:43 mikerod: cbp: As dbasch said, I do not want to pay any overhead for getting a UUID

15:43 Shayanjm: or learn how to build stuff with clojure while using java interfaces

15:43 gotcha catern

15:43 mikerod: I only care about the uniqueness at the per-JVM instance level

15:43 dbasch: Why make your own atom?

15:43 dbasch: The RT/nextID method is not something you think is stable?

15:44 dbasch: mikerod: it's not a documented feature of the language

15:44 mikerod: and it will leave holes in your ids, fwiw

15:45 all it does is use a java AtomicInteger I believe

15:45 jconnoll1: quick and dumb question... I have a vector [1 2 3 4 5], I want to create another vector that's just [0.0 0.0 0.0 0.0 0.0] of length of the first vector...

15:46 mikerod: dbasch: holes do not matter for me, but it being undocumented makes some sense

15:46 cbp: jconnolli: (vec (repeat (count my-vec) 0.0))

15:46 jconnolly: cbp: beauty, thanks

15:47 ndaly: god I love how concise that is

15:48 catern: I wish there was a #(+ % 5) style form for defining functions returning simple data structures, like say #[%] or #{:value %}

15:49 dbasch: you could also do (vec (for [x my-vec] 0.0))

15:49 catern: Simple transformations I mean

15:50 ndaly: catern: I'm confused about what you want to be able to do

15:50 catern: ndaly: define a function returning a vector or map, parameterized with %

15:51 (and the variations on %)

15:51 dbasch: also, (mapv (constantly 0.0) my-vec)

15:51 catern: constantly

15:51 That is a nice function

15:52 thanks dbasch, did not know of it

15:52 dbasch: ,(mapv (constantly 0.0) [:a :b :c])

15:52 clojurebot: [0.0 0.0 0.0]

16:13 fifosine: Is there a standard/good-practice for defining and loading properties from a properties file? For example, I'd like to write a properties file for database credentials and keep it separate from version control.

16:14 bbloom: fifosine: something wrong with slurp and pr-str ?

16:14 er read-str ?

16:15 Raynes: read-str is a thing?

16:15 bbloom: argh.

16:15 read-string

16:15 (def read-str read-string)

16:15 ttasterisco: use environ

16:15 ,(google "clojure environ")

16:15 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: google in this context, compiling:(NO_SOURCE_PATH:0:0)>

16:15 bbloom: then somebody do a vary-meta to :deprecate read-string :-P

16:16 Raynes: Well, he almost certainly wouldn't want read-string.

16:16 fifosine: bbloom: I'm sure there are many ways to do this. Using java.util.Properties is recommended here https://stackoverflow.com/questions/7777882/loading-configuration-file-in-clojure-as-data-structure. I am curious if there is an idomatic way to do this.

16:16 ttasterisco: https://github.com/weavejester/environ

16:16 Raynes: $google clojure environ

16:16 lazybot: [weavejester/environ · GitHub] https://github.com/weavejester/environ

16:16 bbloom: fifosine: depends on what context you want idioms from

16:16 fifosine: A clojure context.

16:16 bbloom: if you're deploying a unix process on heroku or in docker or whatever, use environment

16:17 if you have a jvm cluster w/ devops that know those tools, use java properties

16:17 Raynes: I generally use environment variables for most of my configuration. If I want configuration files, I serialize Clojure data structures by printing them to files and reading them with clojure.edn/read-string

16:17 Or I use toml.

16:17 Lately I mostly use toml for configuration I expect a user to have to modify.

16:17 bbloom: if your config is too big for the environment, put a file path in the environment

16:18 fifosine: bbloom: My config won't be big, it's just going to be a db user and pass as of now

16:18 bbloom: if you don't know anything about java properties, then ignore them

16:18 just use the env

16:18 Raynes: Yeah, you don't want properties for this.

16:18 fifosine: bbloom: When you say, "use the env" do you mean use environ?

16:18 Raynes: ENVIRONMENT VARIABLES

16:19 Environ can handle those for ye

16:19 bbloom: ,(get System/getenv "PATH")

16:19 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to find static field: getenv in class java.lang.System, compiling:(NO_SOURCE_PATH:0:0)>

16:19 Raynes: Though I personally never totally got the purpose of environ.

16:19 bbloom: ,(get (System/getenv) "PATH")

16:19 clojurebot: #<AccessControlException java.security.AccessControlException: access denied (java.lang.RuntimePermission getenv.*)>

16:19 bbloom: aw

16:19 Raynes: I generally just do what bbloom is desperately struggling to do.

16:19 bbloom: i swear that works locally

16:20 Raynes: Haha, yeah, the second one is fine.

16:20 fifosine: lul

16:20 Raynes: I think (System/getenv "PATH") would also work.

16:20 But I can't recall for certain.

16:20 bbloom: Raynes: yup does

16:24 i'm still trying to understand the equals/equiv and hashCode/hasheq dichotomy

16:24 why doesn't hashCode delegate to hasheq ?

16:25 ttasterisco: ,(doc hasheq)

16:25 clojurebot: Titim gan éirí ort.

16:28 bbloom: https://docs.google.com/a/thinkrelevance.com/document/d/1DT2uXlAwH5NstgYSeqbOXb_8K6Gwnw99QksCaUKpCjU/edit?pli=1 says:

16:28 The Java Collections API specifies required algorithms for calculating the hash code of sets, maps, lists, etc from their elements. We wish to be compatible with the collections API

16:28 blargh :-P

16:29 tolitius: is there a way to see what is (file name/function) being compiled? I have a dozen of files, one of which needs aot [hence compiles all the dependent ns], and it takes about 5 minutes to finish (where it should take about 5 seconds), I just want to figure out which file causes the compilation hiccup.

16:30 andyf_: bbloom: Does that answer your question about why they both exist, or only adds to it?

16:30 bbloom: andyf_: it gives me a guess, but i'm still not totally sure

16:31 andyf_: my guess is that java.collections tests hashcode equality in some cases & needs to work with heterogeneous collection impls

16:31 maybe?

16:32 xeqi: bbloom: didn't the 1.6 hash changes break that compatibility?

16:32 bbloom: xeqi: best i can tell both code paths are still there

16:33 andyf_: I am not 100% in the loop on Clojure design decisions, I do believe that they wanted equals and hashCode to be consistent for Clojure collections and their nearest equivalent in the Jaca Collections library

16:33 xeqi: ah, found http://dev.clojure.org/jira/browse/CLJ-1372

16:33 which is about the extent of my knowledge in this area, other then stuff is happening/happened

16:34 andyf_: xeqi: 1.6 should not have changed hashCode ret val for anything

16:34 It did change hasheq ret val for many things

16:40 dbasch: fifosine: you mean a .properties file in the typical java format?

16:43 never mind, had missed the rest of the backlog

16:58 fifosine: How do I debug this issue? http://pastebin.com/3HQFwRmw I know that this jar exists in the repo.

17:01 xeqi: fifosine: by carefulling checking the group:artifact:version in the error

17:01 (missing a q I believe)

17:04 fifosine: xeqi: Still getting it :/ http://pastebin.com/1y6AuLVT

17:16 xeqi: fifosine: that version doesn't exist by that group/artifact: http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22postgresql%22%20AND%20a%3A%22postgresql%22

17:16 perhaps you want group "org.postgres"

17:16 bah

17:16 org.postgresql

17:16 bbloom: is there some way to stop ctrl-c from closing `lein repl` ?

17:16 i want to actually be able to interrupt an evaluation...

17:16 fifosine: xeqi: Looks like that was it!

17:16 amalloy: bbloom: i don't think there's a portable way, but https://github.com/flatland/useful/blob/develop/src/flatland/useful/java.clj#L10-L16 works on some jvms. register a handler for sigint, maybe?

17:16 bbloom: amalloy: but the damn nrepl middleware is called "InterruptableEval"

17:16 c'mon now cemerick/technomancy

17:16 et al

17:16 andyf_: bbloom: In my quick test on Mac OS X with Lein 2.3.4, it already does what you want. Lein 2.4 the behavior changed

17:16 cbp: my lein repl only quits by ctrl-d

17:16 bbloom: andyf_: i just upgraded recently, which would explain why i only started noticing this... i could have sworn it used to work

17:16 cbp: Unless i spam control-c it too many times apparently

17:16 amalloy: oh, yeah. in lein repl, C-c just interrupts for me

17:16 cbp: s/it//

17:16 andyf_: Lein upgrade 2.3.4 should work to downgrade

17:16 bbloom: andyf_: but i want the latest lein for https://github.com/greglook/whidbey

17:16 andyf_: I usually keep a numbered backup of Lein bash scripts before upgrading

17:16 I would have guessed you were kidding when you gave that URL, but looks like a real thing :-)

17:16 bbloom: i wrote fipp in the hope that somebody would integrate it in to nrepl/lein. whedbey realizes that dream :-)

17:16 whidbey*

17:16 andyf_: File a Lein bug, and see where it goes - or maybe there is one already?

17:16 dbasch: lein 2.4.2 on OSX, ctrl-c doesn't kill it

17:16 andyf_: It does for me

17:16 bbloom: https://github.com/technomancy/leiningen/issues/1583

17:16 andyf_: Not sure, but may be a dupe of 1570

17:17 Holy cow - 1538 issues closed on leiningen. That's a bunch

17:19 xeqi: andyf_: and all as a labor of love / no corporate donations

17:19 perhaps sponser would be a better term there

17:19 cbp: you can dotane to tehcnomancys git tip :-P

17:19 donate even

17:20 arrdem: I think he gets like $3.50/wk...

17:20 which is pretty absurd given how much value lein generates.

17:20 andyf_: I've never donated via git tip before. URL handy?

17:20 arrdem: https://www.gittip.com/technomancy/

17:21 cbp: clearly he shouldve been involved in npm instead

17:21 arrdem: lol

17:22 andyf_: No way to do 1 time gift, only periodically?

17:27 bbloom: weird... i'm trying to use yourkit on something in the repl & java.io.PushbackInputStream.read is running on an agent thread (i'm not using agents) & shows as the primary hot method

17:28 it's "own time" metric is climbing rapidly

17:28 s/it's/its

17:28 amalloy: bbloom: it's consuming 100% of a single thread

17:28 that happens all the time with repl/swank. i just right-click and Ignore that method

17:28 bbloom: amalloy: yeah, but why is it doing anything, i'm not evaluating anything

17:29 what's it think it's doing?

17:29 amalloy: it's waiting for you to type something

17:29 that's blocking, so it isn't taking up actual cpu time, but it is time a thread is spending inside a method

17:30 bbloom: odd. hadn't seen that before

17:30 amalloy: i think that's the general outline, anyway

17:30 happens to me anytime i use yourkit on a jvm i'm also attached to via swank

17:30 bbloom: good to know. i had never noticed it with visualvm

17:42 i apparently have no idea how to use yourkit

17:42 (time ...) reports 11 seconds. sum of "own time" yourkit is ~2 seconds

17:42 those don't add up....

17:43 amalloy: own time doesn't include any other functions called by f, in (time (f))

17:43 bbloom: amalloy: i said "sum of"

17:44 amalloy: oh. how are you even summing the own time of all methods invoked by a specific instance of (time (f))?

17:44 bbloom: i manually summed the top 10 calls or so, then multiplied the value of the 11th by the approximate number of rows

17:44 remaining rows

17:44 so that should be an approximate upper bound

17:44 but it's 2ish seconds, instead of 11

17:45 even if that's cpu time, i doubt there's 9 seconds of wall clock waiting

17:49 DilatedPupils|TH: pen tested a site today, able to intercept the request going to paypal and changed the payment to 1p, how many of the sites use the wrong implementation

17:49 arrdem: DilatedPupils|TH: cool result, wrong channel?

17:50 DilatedPupils|TH: sure, sorry

17:50 bbloom: amalloy: found the perf problem with some manually placed (time ...) statements. easy fix

17:50 my experience with profilers is almost always pretty poor

17:54 andyf: dbasch: Try an infinite loop like (count (range)) and then ctrl-c to interrupt it

17:55 dbasch: andyf: works just fine

17:56 andyf: Must be some other diff in our software I guess

18:04 dbasch: andyf: Leiningen 2.4.2 on Java 1.7.0_51 Java HotSpot(TM) 64-Bit Server VM

18:08 andyf: Same here, plus os x 10.8.5 and no ~/.lein/profiles.clj file. Throws exception and exits Lein repl consistently when I try to interrupt evaluation. Seems like Lein/reply folks are on the issue.

18:12 amalloy: bbloom: you must be looking at the wrong stuff. i find yourkit often points me right at the hotspots

18:13 bbloom: i guess i just have no idea how to use it, b/c i put the hotspot back in and tried jvisualvm & it pointed it out right away

18:13 amalloy: i turn on cpu sampling, let it run for a while, capture a snapshot, and then look around in the method list and/or hotspot list

18:14 bbloom: that's exactly what i did

18:14 amalloy: maybe computers just find you offensive

18:14 bbloom: like true

18:15 hiredman: maybe you should have written a map reduce job in erlang

18:15 bbloom: huh?

18:16 hiredman: bad advice for every situation

18:16 ttasterisco: lol

18:19 Shayanjm_: https://gist.github.com/shayanjm/7a085ad77514290c4986 <-- this code immediately prints "Elapsed time: 0.899 msecs"

18:19 but it actually returns values much later

18:19 any ideas how I can capture the WHOLE time it takes to return everything to the last form?

18:20 bbloom: put a doall on your pmap

18:20 hiredman: ugh

18:20 pmap inside a transaction

18:20 bbloom: but yeah, what hiredman said. don't do that

18:20 hiredman: bbloom: that may actually deadlock

18:20 bbloom: that code is all kinds of wrong

18:21 hiredman: does pmap use agents? maybe I am thinking of seque

18:21 bbloom: hiredman: it's built from futures

18:21 hiredman: also ref-set

18:21 bbloom: or maybe it's delays

18:22 amalloy: hiredman: pmap uses futures, seque uses agents

18:22 Shayanjm_: should i throw the pmap into a let, and then throw that into the refset?

18:22 hiredman: terrible thing #1 using pmap, this is indefensible, #2 using the stm, if you try very hard you may be able to defend this

18:22 amalloy: bbloom: http://i.imgur.com/ENtJs.png is the reference from hiredman you seem to have missed

18:23 Shayanjm: hiredman: very very very new to clojure

18:23 what should I do instead?

18:23 bbloom: amalloy: lol awesome

18:23 hiredman: Shayanjm: depends what you are doing

18:24 Shayanjm: hiredman: I have a list of URLS. I have a function that 'gets' the article content body from the URL and stubs it into a string

18:24 hiredman: Shayanjm: but, basically, write functions that take immutable values as arguments, and return an immutable value as a result

18:25 Shayanjm: and then I have another function that analyzes the sentiment of the string glob, and returns a list of numbers signifying each sentence's sentiment

18:25 I would like to be able to iterate through the list of URLS in my 'newswire' ref, and analyze each article's sentiment and store the result in a second ref

18:25 hiredman: why is newswire a ref?

18:26 is it logically a collection of values, or a work queue little machines pull work from?

18:28 Shayanjm: hiredman: It was an atom, but I assumed that I would need some level of transactional guarantee on it and the second 'thing' (whether it's an atom or a ref)

18:28 that way I don't have a set of sentiment analysis results that are out of sync with the list of URLs

18:30 dbasch: Shayanjm: I would make sentiment analysis results be a function of a url snapshot, which is immutable

18:30 Shayanjm: a url snapshot?

18:30 hiredman: Shayanjm: that just isn't a good way to break it up, have a single function that takes a {:title … :url …} and returns a {:title … :url … :sentiment …}

18:30 dbasch: Shayanjm: e.g. nytimes.com/index.html at 3:29 PST 6/28/2014

18:31 Shayanjm: hmmk

18:31 hiredman: then replace newswire with a queue of {:title … :url …}

18:31 dbasch: a url doesn't have a sentiment, the content does

18:31 hiredman: then fire off futures or use an executor directly that runs the function taking one element from the queue at a time

18:32 Shayanjm: Yeah I'm not sure about that fundamentally

18:32 as it stands right now: each component is simplistic and straight forward

18:32 hiredman: collecting the results somewhere (maybe another queue for whatever the next stage is)

18:32 dbasch: (waiting for an example like http://sad-domain/sad-path-to-sadness.html)

18:32 Shayanjm: I'm not sure what composing the functions into one large 'get-sentiment-from-url' function will do for the time issue I was running into

18:33 hiredman: neither pmap nor the stm are simple

18:33 Shayanjm: stm?

18:33 hiredman: Shayanjm: software transactional memory, what dosync and refs are

18:33 Shayanjm: Sure so arguably I don't even need the second ref

18:34 it was just for the sake of having something available to capture the results of the functions

18:34 hiredman: you should not need *any* refs

18:34 Shayanjm: I think a single atom is necessary for managing the data coming in from the API, is it not?

18:34 hiredman: Shayanjm: atoms are not refs

18:34 justin_smith: Shayanjm: http://clojure.org/refs this explains refs / stm

18:35 hiredman: Shayanjm: and in any case I suspect a work queue would be better

18:35 Shayanjm: Probably, hiredman. Do you suggest I build one myself or is there a library option available?

18:36 hiredman: Shayanjm: java.util.concurrent has a few queues

18:37 Shayanjm: Anyway, as I mentioned before - I don't know how this has anything to do with the weirdness surrounding the time function

18:37 hiredman: you could pull in core.async and use a channel as a work queue too

18:38 Shayanjm: pmap is sort of lazy

18:38 Shayanjm: does anyone know why time is being printed before every form has finished evaluating?

18:38 oh really?

18:38 bbloom: Shayanjm: i answered your question in my very first comment: try doall

18:38 hiredman: Shayanjm: did you read the doc string for pmap?

18:38 justin_smith: Shayanjm: a function can return a result that is lazy before the result is realized

18:38 hiredman: (doc pmap)

18:38 clojurebot: "([f coll] [f coll & colls]); Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the time of f dominates the coordination overhead."

18:38 bbloom: it will prevent the laziness.... butthen you should listen to hiredman

18:38 Shayanjm: ok thanks bbloom

18:38 I see

18:39 hiredman: but pmap is terrible

18:39 ~pmap

18:39 clojurebot: pmap is not what you want

18:39 bbloom: (dec pmap)

18:39 lazybot: ⇒ -1

18:39 bbloom: sheesh, that's too almost positive

18:39 (dec pmap)

18:39 lazybot: ⇒ -2

18:39 bbloom: (dec pmap)

18:39 lazybot: ⇒ -3

18:39 bbloom: (dec pmap)

18:39 lazybot: Do I smell abuse? Wait a while before modifying that person's karma again.

18:39 bbloom: better

18:40 Shayanjm: wait so what is pmap useful for then?

18:40 hiredman: nothing

18:40 Shayanjm: My understanding is that it's just like map, but it threads each iteration?

18:40 (apparently clojure for the brave lied to me)

18:41 bbloom: that is what it is, it's just that that is not useful

18:41 hiredman: it isn't just that

18:41 tuft_: is there a preferred alternative these days?

18:41 justin_smith: bbloom: wouldn't it still be useful, if your function was more expensive than the future spawning overhead?

18:41 hiredman: it also imposes an ordering on the results, it trys to run only as many jobs as there are cores at a time

18:41 it is semi lazy

18:41 but then does weird things on chunked seqs

18:42 all of those things are basically things you never want

18:44 I recommend getting familiar with the executors framework http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html etc

18:45 a fundamental problem of pmap is it takes in a seq and produces a seq

18:45 the seq abstraction is terrible for parallelism because it enforces linear access

18:46 tuft: ".. but i was promised if i used seqs and maps i'd get parallelism for free? 😢 "

18:47 hiredman: by who?

18:48 * cbp grabs the baseball bat

18:48 tuft: haha

18:48 can't remember exactly where that came from

18:48 hiredman: http://xahlee.info/comp/i/ICFPAugust2009Steele.pdf

18:48 tuft: generally getting more abstract than a for loop seems to have that promise though

18:49 hiredman: sure

18:49 in order to have parallelism you need a datastructure with random access

18:50 tuft: that makes sense

18:51 dbasch: hiredman: that's not strictly true, you can have a sequential pipeline of things that execute in parallel

18:55 hiredman: dbasch: concurrent vs. parallel

18:56 dbasch: hiredman: yes, I meant parallel, as in a factory pipeline with workers doing things in parallel

18:57 danielszmulewicz: Is clj-time still the best option to work with times in Clojure? I need to determine if a given date is in the future.

18:57 dbasch: in order to have parallelism you just need entities who have work to do

18:57 hiredman: dbasch: they are not concurrent, the "pipeline" sychronizes access

18:58 dbasch: hiredman: you said parallelism, not concurrency

18:58 seancorfield: danielszmulewicz: depends on what format your initial date is... java.util.Date or Joda Time?

18:58 danielszmulewicz: seancorfield: java.util.Date (it's coming from Monger)

18:58 seancorfield: At World Singles we use both date-clj (for java.util.Date stuff) and clj-time for more complex stuff

18:58 date-clj/before? is probably the easiest then

18:59 justin_smith: ,(compare (java.util.Date.) (java.util.Date.)) danielszmulewicz

18:59 danielszmulewicz: seancorfield: Very cool. Thank you.

18:59 clojurebot: 0

18:59 hiredman: dbasch: I said lots of things

18:59 justin_smith: you don't need to get fancy for that

18:59 danielszmulewicz: justin_smith: Thanks. That's cool as well.

18:59 justin_smith: I mean if you need to do math on time objects, or read format strings, yeah use a lib

18:59 dbasch: hiredman: I was commenting on "hiredman: in order to have parallelism you need a datastructure with random access"

19:00 justin_smith: but you don't need anything but the built in class for comparing sequentiality

19:00 danielszmulewicz: justin_smith: Just this one, and maybe one or two more.

19:00 amalloy: &(frequencies (repeatedly 10000 #(compare (java.util.Date.) (java.util.Date.))))

19:00 lazybot: ⇒ {0 9991, -1 9}

19:00 justin_smith: fascinating

19:01 amalloy: not really important to this discussion, but i thought you might like it, justin_smith

19:01 justin_smith: indeed

19:01 danielszmulewicz: amalloy: Care to explain to a dummy?

19:01 amalloy: danielszmulewicz: you build two date objects and compare them. usually, they're in the same millisecond

19:01 ndaly: wow

19:01 amalloy: but every so often, you slip across a millisecond boundary between building the first and building the second, so they compare as different

19:01 danielszmulewicz: amalloy: Oh, nice.

19:02 ndaly: wait, is that building 10000 pairs of date objects?

19:02 amalloy: yeah

19:02 ndaly: very nice

19:02 amalloy: i suppose it would have been more apropos to generate them all in parallel with pmap

19:03 justin_smith: yeah, the jvm handles micro-liftime objects very nicely

19:03 ndaly: I wonder how much of the JVM being good can be attributed to it needing to make up for Java being bad

19:04 justin_smith: ndaly: I think there is more the fact that very well funded companies poured a lot of resources and exceptional talent into the jvm

19:05 amalloy: incidentally, that frequency chart gives a good estimate of how long it takes to construct a Date object. 0.1% of a millisecond, right? so ##(time (dotimes [_ 1000] (java.util.Date.))) should take about 1ms

19:05 lazybot: ⇒ "Elapsed time: 7.151076 msecs" nil

19:06 amalloy: hmph. i want a refund. i don't know why that's off by a factor of 7

19:06 hiredman: the jvm it does things

19:09 danielszmulewicz: (+ seancorfield)

19:09 hehe, how does this karma things work again?

19:09 oskarkv: inc

19:09 danielszmulewicz: right, thanks

19:09 (inc seancorfield)

19:09 lazybot: ⇒ 13

19:09 amalloy: hiredman: yeah, i guess that's what it is. if i go from 1000 dates to 10000, the time taken only doubles

19:09 danielszmulewicz: (inc justin_smith)

19:09 lazybot: ⇒ 51

19:09 seancorfield: thank you danielszmulewicz!

19:10 danielszmulewicz: seancorfield: Thank you!

19:10 (inc amalloy)

19:10 lazybot: ⇒ 134

19:12 dbasch: &(time (dotimes [_ 1000]))

19:12 lazybot: ⇒ "Elapsed time: 3.850407 msecs" nil

19:13 dbasch: (dec dotimes)

19:13 lazybot: ⇒ -1

19:13 dbasch: ,(time (dotimes [_ 1000]))

19:13 clojurebot: "Elapsed time: 0.164555 msecs"\n

19:14 bbloom: ,(dotimes [_ 10] (time (dotimes [_ 100])))

19:14 clojurebot: "Elapsed time: 0.136017 msecs"\n"Elapsed time: 0.004059 msecs"\n"Elapsed time: 0.003686 msecs"\n"Elapsed time: 0.00368 msecs"\n"Elapsed time: 0.003563 msecs"\n"Elapsed time: 0.003803 msecs"\n"Elapsed time: 0.003647 msecs"\n"Elapsed time: 0.003657 msecs"\n"Elapsed time: 0.003569 msecs"\n"Elapsed time: 0.003598 msecs"\n

19:14 bbloom: ,(dotimes [_ 10] (time (dotimes [_ 1000])))

19:14 clojurebot: "Elapsed time: 0.152137 msecs"\n"Elapsed time: 0.025343 msecs"\n"Elapsed time: 0.209708 msecs"\n"Elapsed time: 0.002701 msecs"\n"Elapsed time: 0.00244 msecs"\n"Elapsed time: 0.002395 msecs"\n"Elapsed time: 0.002409 msecs"\n"Elapsed time: 0.002404 msecs"\n"Elapsed time: 0.002389 msecs"\n"Elapsed time: 0.002377 msecs"\n

19:14 bbloom: computers. how do they work?

19:16 gfredericks: ,(macroexpand-1 '(dotimes [_ 1000]))

19:16 clojurebot: (clojure.core/let [n__4379__auto__ (clojure.core/long 1000)] (clojure.core/loop [_ 0] (clojure.core/when (clojure.core/< _ n__4379__auto__) (recur (clojure.core/unchecked-inc _)))))

19:17 danielszmulewicz: $help

19:17 lazybot: You're going to need to tell me what you want help with.

19:17 amalloy: what in the world. did i turn this into #dotimes?

19:17 danielszmulewicz: dbasch: What is the meaning of the ampersand at the beginning of the expression you typed earlier?

19:18 cj3kim: hi, in (defn [& args] ;code ) is args an vector?

19:18 dbasch: danielszmulewicz: asking lazybot to evaluate

19:18 amalloy: cj3kim: it's a seq

19:18 danielszmulewicz: dbasch: is that not the coma?

19:18 dbasch: danielszmulewicz: that's clojurebot

19:18 cj3kim: amalloy: thank you!

19:18 danielszmulewicz: dbasch: oh, how many bots do we have here?

19:19 amalloy: at least two. jury's still out on justin_smith

19:19 dbasch: danielszmulewicz: I am not a bot

19:19 danielszmulewicz: hehe

19:19 dbasch: I am a 13 year old boy from Ukraine

19:20 ttasterisco: ew

19:21 bbloom: Bronsa: i think i'm gonna have to start on the compiler sooner rather than later... the more of core i make symbolic, the slower everything goes... i'm working on lazy seqs now, it's making everything 20X slower (which i guess is expected for interpreter vs compiler)

19:23 amalloy: bbloom: i wonder, are you chunking lazy seqs? that brings a surprisingly large speedup

19:24 bbloom: amalloy: just the overhead of the itnerpreter for first/next/seq dispatch is killing me

19:27 justin_smith: amalloy: me? Ha! I would appreciate it if you would continue.

19:28 amalloy: Why would you appreciate it if I would continue?

19:29 justin_smith: What do you think?

19:29 dbasch: now this is #clojure-chatbots

19:33 TEttinger: bbloom, is this for clojure-in-clojure?

19:33 bbloom: TEttinger: not for the official c-in-c stuff going on in tools analyzer etc. it's for my hacky thing

19:33 amalloy: dbasch: for some reason back in march i spent a few days as /nick amalloybot instead of amalloy. i don't really remember why i thought this was funny

19:34 er, hours. not days. jeez

19:34 dbasch: amalloy: were you trying to pass the reverse turing test?

19:35 amalloy: the only person who really believed i had become a bot was bbloom

19:36 bbloom: amalloy: i mean, it would explain your code golf skills

19:36 you're clearly a search algorithm

19:42 cj3kim: how do you know which index the for loop is processing for every cycle? ie if I wanted to know what index (for row[matrix]) was processing?

19:42 hiredman: ~for

19:42 clojurebot: for is awesome

19:43 hiredman: erm

19:43 ~for

19:43 clojurebot: for is swanking

19:43 hiredman: feh

19:43 for isn't a loop

19:43 (says so in the doc string if I recall)

19:43 Glenjamin: ,(doc for)

19:43 clojurebot: "([seq-exprs body-expr]); List comprehension. Takes a vector of one or more binding-form/collection-expr pairs, each followed by zero or more modifiers, and yields a lazy sequence of evaluations of expr. Collections are iterated in a nested fashion, rightmost fastest, and nested coll-exprs can refer to bindings created in prior binding-forms. Supported modifiers are: :let [binding-form expr ...], ...

19:43 hiredman: "List comprehension"

19:43 justin_smith: cj3kim: the classic is to use map-indexed on the sequence (for [[i e] (map-indexed identity elements)] ...)

19:44 where i will be the number, e the element

19:44 cj3kim: oh :[

19:44 hiredman: justin_smith: identity doesn't work

19:44 Glenjamin: although if your for is simple, you're probably better off doing the work in the fn passed to map-indexed

19:44 justin_smith: hiredman: oh, it needs two args, sorry

19:44 (for [[i e] (map-indexed list elements)] ...)

19:45 hiredman: http://en.wikipedia.org/wiki/List_comprehension

19:45 michaniskin: (def indexed (partial map-indexed vector))

19:45 cj3kim: thank you

19:46 hiredman: that use of map-indexed is also vaguely amusing, because map-indexed was created because there was some contrib function that created indexed sequences

19:46 and people wanted it in core, but rich hated the idea of constructing pairs when you are just going to rip them apart again

19:47 amalloy: hiredman: named indexed, in fact

19:47 hiredman: it is a hilarious cycle

19:47 maybe ridiculous cycle would be a better name

19:47 amalloy: http://clojuredocs.org/clojure_contrib/clojure.contrib.seq/indexed

19:49 there is some weird stuff in old contrib

19:49 michaniskin: it's something you need to do sometimes, deal with it lol

19:50 hiredman: if you don't give people a way to do what they want easily, even if it is inefficient, they are just going to go out of their way to do it and complain about the difficulty

19:50 dbasch: hiredman: hence pmap :P

19:51 amalloy: map-vals being hiredman's favorite example of this, i would think

19:52 hiredman: amalloy: there are too many examples of this in clojure to pick a favorite

19:52 justin_smith: michaniskin: fyi, I just benchmarked w/ criterium, and vector takes 3 times as long as list in a test case where I just add the results (vectors are high overhead for small collections)

19:52 https://www.refheap.com/87634

19:53 michaniskin: justin_smith: vectors are nice though because using things like indexed in macros, you don't want to inadvertently evaluate the items in there

19:55 if you emit lists you have to watch out for that

19:58 justin_smith: michaniskin: good news is, with hotspot turned on, both run much faster, and the difference is very small

19:58 cj3kim: justin_smith: for loop isn't working. could you take a look at the gist and let me know what's up? https://gist.github.com/cj3kim/01279c340d54db9a5caf

19:58 justin_smith: michaniskin: https://www.refheap.com/87634 updated with hotspot results

19:59 amalloy: justin_smith: that benchmark shows vector being way faster than list, not the other way around

19:59 dbasch: cj3kim: for is not a loop

19:59 justin_smith: cj3kim: as mentioned before, it is not a for loop

19:59 dbasch: cj3kim: you want doseq

19:59 justin_smith: cj3kim: calling it a loop is misleading

19:59 michaniskin: justin_smith: wow, that's a pretty big improvement

19:59 cj3kim: got it

19:59 thank you

19:59 dbasch: it's unfortunate that for means one thing in math and another in imperative languages

20:00 justin_smith: cj3kim: calling dimension-index as if it was a function makes no sense

20:00 amalloy: it's probably mostly the time spent destructuring, not the time spent on actually building the lists/vectors

20:00 justin_smith: that should be giving an error

20:00 that is not how for works

20:00 (or doseq for that matter)

20:01 cj3kim: justin_smith: i'm very new to clojure and i'm sure I'm committing grave sins

20:01 justin_smith: not sins, just invalid function calls

20:01 dbasch: cj3kim: the important thing here: for creates a lazy sequence

20:01 cj3kim: got it

20:02 dbasch: cj3kim: you don't want a lazy sequence, you want to iterate over something for side effect

20:02 s

20:02 justin_smith: also, it looks like, based on your error message, something in your core ns is shadowing the definition of for

20:03 dbasch: justin_smith: the error I see is legit

20:03 he is passing 3 arguments to for

20:03 amalloy: justin_smith: yeah, that's a normal error for for

20:03 justin_smith: oh, never mind

20:03 amalloy: there's no implicit-do, because you're not supposed to do side effects

20:04 justin_smith: I thought it had an implicit do, my bad

20:04 I guess I never bothered trying to put more than one expression in a for

20:04 odd

20:05 dbasch: I do that for debugging once in a while, and wrap everything in a do

20:05 cj3kim: solved, thanks guys

20:05 my background is in oo javascript so clojure has been a mind fuck

20:19 Shayanjm: hiredman: I know you said not to use pmap - but it's cutting down execution time by 50%

20:19 (as opposed to just throwing it into a map. Haven't experimented with a job queue yet)

20:22 hiredman: mashing the accelerator to the floor and not letting up goes fast too

20:36 tuft: maybe not an efficient way to get somewhere fast, but it does work!

20:39 danielszmulewicz: Is there not a built-in map that prunes nils? Is that a bad design idea?

20:39 hiredman: ,(doc keep)

20:39 clojurebot: "([f coll]); Returns a lazy sequence of the non-nil results of (f item). Note, this means false return values will be included. f must be free of side-effects."

20:41 danielszmulewicz: hiredman: Oh, nice. Am I being disingenuous if I ask why does f has to be free of side-effects?

20:42 amalloy: danielszmulewicz: "must be free of side effects" has been sprinkled around the clojure.core docstrings as seasoning

20:43 danielszmulewicz: amalloy: Exactly my point.

20:43 (inc amalloy)

20:43 lazybot: ⇒ 135

20:43 danielszmulewicz: (inc hiredman)

20:43 lazybot: ⇒ 48

20:43 amalloy: it's not any more true for keep than it is for map, which is to say you should be careful with side effects as always, but nothing drastic will happen if you ignore that warning

20:45 danielszmulewicz: amalloy: Very true. The docstrings were always throwing me off. What? I can't do that? But it is exactly what I need! Now I just ignore them, but like you say, act with caution.

20:49 ,(false? nil)

20:49 clojurebot: false

20:49 danielszmulewicz: ,(if nil "ee" "rr")

20:49 clojurebot: "rr"

20:49 danielszmulewicz: jeez

20:49 or should I say wat?

20:56 rplaca: danielszmulewicz:

20:56 ,(true? "hello")

20:56 clojurebot: false

20:57 rplaca: ,(if "hello" "ee" "rr")

20:57 clojurebot: "ee"

21:01 danielszmulewicz: rplaca: exactly.

21:01 rplaca: also:

21:01 ,(nil? false)

21:01 clojurebot: false

21:02 danielszmulewicz: rplaca: to be included in a wat series

21:02 amalloy: danielszmulewicz: true? and false? ask "is this the boolean true [or false]", not "would this be treated as truthy or falsey in a boolean context?"

21:02 rplaca: true?, false? and nil? are equality predicates not thuthiness predicates

21:02 amalloy: you're apparently looking for ##(doc boolean)

21:02 lazybot: ⇒ "([x]); Coerce to boolean"

21:02 rplaca: *truthiness

21:03 danielszmulewicz: rplaca: all correct, but still not friendly.

21:04 rplaca: doesn't seem to difficult to me. nil and false are falsey and everything else is truthy

21:04 gfredericks: danielszmulewicz: what would you use a truthy? function for?

21:04 danielszmulewicz: http://langnostic.blogspot.co.il/2013/05/truthy-and-falsy-vs-explicit.html

21:04 amalloy: danielszmulewicz: you'd *really* be saying "wat" if (= true x) gave different results than (true? x)

21:04 rplaca: turns out to be what you want almost all the time in idiomatic code

21:05 amalloy: this is just a case of "gosh, i'm asking a question different than the one i meant to, and the computer is answering the question i'm actually asking"

21:05 danielszmulewicz: That is true.

21:05 gfredericks: I guess boolean == truthy?, and not == falsy?

21:06 so we already have them

21:06 boolean isn't strictly very useful though

21:07 I keep using it where I don't quite need to

21:07 danielszmulewicz: I like the "non-conclusion" of the author of this post: http://langnostic.blogspot.co.il/2013/05/truthy-and-falsy-vs-explicit.html

21:09 rplaca: It should be noted that in his empty list example, the idiomatic clojure would be (yay-nay (seq '()))

21:09 gfredericks: clojure's truthiness violates the zero-one-infinity rule

21:09 amalloy: gfredericks: aha, but without boolean how could we write pithy truthiness examples? ##(group-by boolean [true false () nil {} "" 0])

21:09 lazybot: ⇒ {true [true () {} "" 0], false [false nil]}

21:09 gfredericks: amalloy: w000h pith!

21:10 test.check has an alternate truthiness paradigm internally

21:10 https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check.clj#L29-32

21:11 danielszmulewicz: The more I learn about Haskell, the more I'm drawn to it. So appeallingly clean and logical.

21:14 amalloy: gfredericks: that is weird as heck. it's hard to imagine it being used in a way that doesn't make it hard to write tests for which returning (not throwing) exceptions is the expected behavior

21:14 rplaca: gfredericks: did Reid get that from quick-check or did he do it to fit what he was doing?

21:15 ybit2: https://github.com/swannodette/om/wiki/Conceptual-overview

21:15 """Functional programming is not a silver bullet but its emphasis on unadorned data is a guiding light. No models."""

21:15 would someone mind explaining this?

21:16 rplaca: gfredericks: oh - but you don't *always* have to use that, do you?

21:16 ybit2: https://github.com/heath/treemap/blob/master/app/models/trees.coffee

21:16 i'm not validating the data passed around

21:17 oskarkv: ybit2 what is it that you don't understand, about that quote? :P

21:19 I'm going to bet, but ybit2 you might wanna watch this http://www.infoq.com/presentations/Value-Values

21:19 ybit2: i'm not entirely sure why you wouldn't need models, i think the answer for "what goes in its place" is "persistent data structures"

21:19 oskarkv: bed* :P

21:19 gfredericks: amalloy: that's my reaction too, but considering that the tests are supposed to be predicate-like, I don't think there's any realistic use for that

21:20 or at least wrapping it in boolean is an easy workaround

21:20 rplaca: it's an internal function, the user doesn't use that at all; but amalloy is right that if your test returns an exception it will be misinterpreted

21:21 * gfredericks confirms it

21:22 rplaca: ahh, interesting

21:22 gfredericks: it's exactly as inhibiting as if (is (Exception. "")) fails

21:23 oskarkv: ybit2 I'm not entirely sure about the "No models" thing. :P It leaves much to the imagination.

21:24 ybit2: hah :)

21:24 he was saying that facts have "set" methods

21:24 i'm so glad that was a joke :)

21:24 oskarkv: hehe yeah

21:24 gfredericks: Integer#setPositive

21:25 amalloy: gfredericks: i'm really surprised that someone who wrote a monad-based testing library would do that. like, surely it's possible to build an Either Result Failure, and know the difference between (Left (Exception.)) and (Right (Exception.))

21:25 * gfredericks kind of wants to make an OOP parody language

21:26 gfredericks: amalloy: I actually wrote that function, but was just refactoring some logic that was already there; but yeah I agree

21:26 I was thinking of making a microlibrary with that the other day

21:26 ,(defrecord Either [val ex])

21:26 clojurebot: sandbox.Either

21:27 gfredericks: wait that doesn't work :P

21:27 ,(defrecord Either [val ex?] clojure.lang.IDeref (deref [_] (if ex? (throw val) val)))

21:27 clojurebot: sandbox.Either

21:28 gfredericks: ,(defmacro eitherly [ex-class expr] `(try (Either. ~expr false) (catch ~ex-class e# (Either. e# true))))

21:28 clojurebot: gfredericks: Pardon?

21:28 gfredericks: clojurebot: fine.

21:28 clojurebot: Cool story bro.

21:29 reiddraper: gfredericks: amalloy: one of you mind filing an issue?

21:29 gfredericks: amalloy: dangit now look what you did

21:30 reiddraper: :D

21:30 gfredericks: reiddraper: should we have a whole namespace with some Either functions?

21:30 amalloy: gfredericks: it's either that or nothing

21:31 reiddraper: I agree that returning an exception should not count as a failure

21:32 gfredericks: amalloy: MULTIMONADIC PUN

21:33 amalloy: forever $ putStrLn "lol"

21:36 blur3d: has anyone had problems with maps/deref working properly in async/go blocks?

21:36 actually.. let me update some dependancies first

21:37 hiredman: ~anyone

21:37 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

21:38 blur3d: hiredman: can you rephrase the above into an example message?

21:38 hiredman: "I got error message X, what am I doing wrong?"

21:39 blur3d: sure, but in this case there is no error

21:39 amalloy: blur3d: "when i do X in a go block, Y happens, which makes me think something is wrong with deref"

21:39 danielszmulewicz: "Thruthiness" is not a thing. It is subjective and language-dependent. Logical truth is objective and can be reasoned about without intermediate or underlying implementation details. That's what bothers me.

21:39 blur3d: and it is likely a dependancy bug

21:39 hiredman: "I have problem X, what am I doing wrong?"

21:40 blur3d: not sure I agree still, but let me check dependancies before I try again

21:40 hiredman: having problems with X is the general state of programming, if you want to really discuss things you need to be more specific

21:41 the most specific being a pastebin of code and a description of the problem you have with it

21:42 amalloy: hiredman: i feel compelled to come up with more specific problem statements

21:43 hiredman: amalloy: huh?

21:43 amalloy: "here is a snapshot of a VM; if you boot it up and do xyz, you'll encounter problem abc"

21:43 (more specific than a pastebin of some code)

21:44 hiredman: amalloy: the purpose of the pastebin of code is so others can read it, not execute it

21:44 I've never tried to read a vm to determine what will happen when I boot it

21:48 oh man, I just had an idea

21:49 imagine an irc room for writers, who are, you know, working on their prose

21:49 gfredericks: danielszmulewicz: truthiness is how dynamically typed languages deal with the possibility of arbitrary objects being used in a condition

21:50 hiredman: and they never share what they have actually written for review, they just sort of trade vague descriptions of their work to see what others think

21:50 gfredericks: danielszmulewicz: the only way to avoid partitioning things into truthy and falsy is to throw an exeception when non-booleans are used

21:51 hiredman: "I have this chapter, it is written in the third person, but I don't think it works, what should I do?"

21:51 "have you tried showing and not telling?"

21:52 gfredericks: "does anybody here have experience with alternating between first-person and third-person each chapter?"

21:52 hiredman: "I killed my pov character, but there is more story to tell, what do I do?"

21:54 catern: haha

21:54 amalloy: "i've been practicing by reading moby dick, and i think it would be better without the whale. can someone help me do that?"

21:54 catern: "Whenever I read one of my chapters I get a NoPlotFoundException, can anyone help?"

21:55 gfredericks: amalloy: "you thinking about it all wrong"

21:56 danielszmulewicz: gfredericks: Very interesting. Truthiness is a property then, not a value. When it is encoded in a type, you don't need to infer that property. I'm just wondering how more convenient that is in practice. I wish people with experience with Haskell could weigh in.

21:56 rplaca: danielszmulewicz: thuthiness may not be a thing but defining in a way that fits with the other paradigms of the language can lead to cleaner, more readable code

21:56 gfredericks: danielszmulewicz: well statically typed languages avoid the issue altogether since they can enforce booleans-only at compile time

21:56 does scala do that?

21:57 hiredman: writing prose continues to be my favorite analog for writing code

21:57 rplaca: dynamic laguages could do that to (just like Clojure won't do + except on numbers)

21:57 amalloy: danielszmulewicz: haskell doesn't really care about truthiness, because using booleans is not super-common; you just pattern-match on stuff

21:58 rplaca: but everyone would just be annoyed by it :)

21:58 amalloy: Bool and if aren't language built-ins; the former is just `data Bool = True | False`, and if is just `if :: Bool -> a -> a -> a; if True t _ = t; if False _ f = f`

21:59 (well, it's not *really* that, because of the if/then/else syntax. but it could be)

22:00 danielszmulewicz: One thing is for sure: truthiness is not spread across dynamic languages in a uniform way, which means that in practice you need to remember language-specific things when dealing with conditions. Annoying.

22:01 rplaca: danielszmulewicz: true, but it's more important that it fit the paradigm of the specific language.

22:01 and it's not *that* hard to remember if you're writing more than a few lines of code in the language

22:02 amalloy: if every language were the same, they'd all be the same. what fun would that be?

22:06 danielszmulewicz: amalloy: I'm still stuck in the fantasy of the "ultimate" language. I should get over it...but only after learning Haskell :-)

22:11 geardev: is a multi-method kind of like pattern matching in haskell?

22:11 gfredericks: what they don't tell you is that after learning haskell you have to start wanting to learn idris

22:11 geardev: it has some overlap; multimethods support inheritance in a couple ways too

22:12 another big difference is that multimethods are open

22:12 danielszmulewicz: gfredericks: spot on. Very true. Dependent types is the next thing.

22:12 gfredericks: there's no end.

22:13 geardev: multimethods are like pattern matching, but they also have inheritance

22:14 gfredericks: actually any similarity to pattern matching is pretty shallow

22:17 Frozenlock: bbloom: I updated cljs for a project and I get weird errors which seem related to metadata. Do you know if there was some mentions of problems for metadata recently? (say since 0.0-2173)

23:23 halogenandtoast: If anyone is feeling particularly generous, I’m trying to write a game in which cards are dealt to players but I can’t seem to get the logic right. Currently I get “clojure.lang.Cons cannot be cast to clojure.lang.IF” at I think line 57 of https://gist.github.com/halogenandtoast/58cf169f271d49f69005 but haven’t been able to figure out why. I bet there are a number of things I’m doing wrong so any help would be

23:23 much appreciated.

23:24 trptcolin: ,(doc update-in)

23:24 clojurebot: "([m [k & ks] f & args]); 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a function that will take the old value and any supplied args and return the new value, and returns a new nested structure. If any levels do not exist, hash-maps will be created."

23:25 trptcolin: halogenandtoast: update-in wants the thing where you have `new-hand` to be a function

23:25 that’s what the “clojure.lang.Cons cannot be cast to clojure.lang.IFn” error msg is trying to tell you

23:26 halogenandtoast: trptcolin: makes sense.

23:27 it almost works now, the conj doesn’t really like my values but I can work with that.

23:28 switched conj to into, much better

23:29 Thanks trptcolin

23:29 trptcolin: halogenandtoast: sure.

23:29 halogenandtoast: I feel like most of what I wrote could be more succint, but I’m just not there yet.

23:31 trptcolin: yeah, if you wanted you could probably collapse those 3 lines with the `let`s into 1 with update-in, something like (update-in state [:players player-number :hand] into cards)

23:32 halogenandtoast: Yeah the let for the hand isn’t used.

23:32 (update-in state [:players player-number :hand] #(into cards %))

23:34 trptcolin: ah right you want cards first

23:34 halogenandtoast: At least I think I do, the whole functional aspect of this is warping my brain.

23:35 trptcolin: nice. it gets easier

23:37 halogenandtoast: I’d imagine. I figured this would be a good exercise to start understanding clojure.

23:39 trptcolin: cool, yep

Logging service provided by n01se.net