#clojure log - Jul 03 2014

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

2:05 [Neurotic]: Hi, I've used extend-type, but no matter what I do, I can't seem to get it t compile. It keeps giving me 'unable to resolve symbol'. I'm not sure what I'm doing wrong here? https://www.refheap.com/87821

2:06 I've done something stupid, but I can't see what it is

2:35 ddellacosta: [Neurotic]: what is get-value?

2:36 [Neurotic]: ddellacosta: what do you mean? it's defined on line 21

2:36 ddellacosta: [Neurotic]: oh, I see, sorry

2:36 [Neurotic]: Ah cool. Wasn't sure if I was crazy :)

2:36 ddellacosta: [Neurotic]: try requiring storm.trident.testing in the same ns declaration

2:37 [Neurotic]: damnit, sorry, you are. I must be sleepy today

2:37 [Neurotic]: nope, no win :(

2:37 unfortunately :/

2:37 ddellacosta: [Neurotic]: well, wait, where is the type declared?

2:38 [Neurotic]: it's a Java type.

2:38 ddellacosta: oh

2:38 [Neurotic]: it's imported on line 15

2:38 ddellacosta: [Neurotic]: right, thought it was a type though

2:40 [Neurotic]: have you tried importing the get-value fn from marceline.storm.trident where the Protocol is defined?

2:40 [Neurotic]: I think that's actually what you want to be doing vs. :refer :all from marceline.storm.testing

2:41 Viesti_: hum

2:41 Viesti: doh, I had a tail!

2:42 [Neurotic]: [marceline.storm.testing :refer [get-value]] << like so? says it doesn't exist

2:42 ddellacosta: [Neurotic]: also, it may be the case that you have to define multiple-arity get-value separately: https://groups.google.com/d/msg/clojure/XeY7MGrcxLQ/6fMfdoWzjWMJ

2:43 [Neurotic]: ddellacosta: ooh, lemme try that

2:43 Viesti: why do <,>,=,<=,>= return true in the single argument case?

2:43 ddellacosta: [Neurotic]: also, not [marceline.storm.testing :refer [get-value]] but rather [marceline.storm.trident :refer [get-value]]

2:44 Viesti: we had a discussion on another channel where a guy had a bug in his code where he passed only one argument to =

2:44 I understand and quite like of the generality in say <

2:44 but maybe the one arg case is a bit confusing

2:45 this haskell guy was of the opinion that such generality should live elsewhere, but thought about having a good argument on why to keep it in those functions. The generality is at least close in the source code :)

2:48 ddellacosta: Viesti: I think you'd probably get a good answer on the mailing list, but I don't have much other than a guess, which is to maintain consistency with other Clojure functions. But that's just a guess.

2:50 [Neurotic]: did it work?

2:50 [Neurotic]: ddellacosta: nope, but I think I have another idea... need to try it

2:51 ddellacosta: [Neurotic]: multiple declarations per arity + that require didn't work? Hmm

2:52 [Neurotic]: I don't *think* so, I've kinda scrapped it, and trying it again, see if I did something stupid

2:53 ddellacosta: [Neurotic]: well, I don't have any great ideas past that; I hope you figure it out! Good luck

2:54 [Neurotic]: oh, one more stupid freaking thing actually--I've had trouble when I had the import at the top of the ns statement vs. bottom, believe it or not

2:54 [Neurotic]: ddellacosta: looks like the refer worked for a friend of mine... I may try out his code

2:55 ddellacosta: [Neurotic]: okay, hope that works for you

2:57 [Neurotic]: ddellacosta: yep, working looks like. Actually needed a [marceline.storm.trident :refer [get-value]]

2:57 which brought in the get-value function from the protocol, so it knew what was going on

2:57 ddellacosta: [Neurotic]: ah okay, great

2:58 [Neurotic]: thought it may be related

3:10 Viesti: ddellacosta: common lips has same single arity case for =,< etc.

3:11 of course should have looked there :)

3:12 [Neurotic]: ddellacosta: yep, all passing now :) Thanks for your help!

3:12 ddellacosta: Viesti: what's the reason there?

3:12 [Neurotic]: great! Glad you got it working.

3:40 Viesti: ddellacosta: didn't find out yet

4:06 petrust: How to combine secretary with Om? Should one manipulate the app state atom and then conditionally render in the main Om fn?

4:06 Or is there a different om call that I can call from my defroute fns?

4:08 borkdude: petrust I have an example of this

4:09 petrust: thx, borkdude :)

4:09 borkdude: petrust this might give you an idea:

4:09 https://www.refheap.com/87825

4:10 petrust call define-routes from will-mount

4:10 it needs the access to the data argument provided to the Om component

4:10 that's why I used this construction

4:11 petrust some more code: https://www.refheap.com/87826

4:12 hope this answers your question a bit

4:12 petrust: thanks, borkdude!

4:38 I’m having a weird issue with dependencies, specifically related to dependencies.

4:38 *related to secretary

4:38 I’ve added [secretary "1.2.1-SNAPSHOT"] to project.clj deps

4:38 I ran> lein clein

4:38 and lein cljsbuild clean

4:38 if I run lein deps, I get no output, so presumably all deps are satisfied

4:38 but if I now try to run lein cljsbuild auto, I get the following error:

4:39 Caused by: java.io.FileNotFoundException: Could not locate secretary/core__init.class or secretary/core.clj on classpath:

4:42 noidi: lein classpath | grep secretary

4:42 is the JAR on the classpath?

4:43 petrust: yes

4:43 it’s there

4:44 - /Users/petrus/.m2/repository/secretary/secretary/1.2.1-SNAPSHOT/secretary-1.2.1-SNAPSHOT.jar:

4:46 noidi: unfortunately I don't know enough about cljsbuild to help you :/

4:46 petrust: downgraded dep to 1.2.0, same error.

4:48 ddellacosta: petrust: did you include secretary in any source files, or did you merely add it to the project.clj dependencies?

4:48 petrust: addid it to project.clj and :require it in my main.cljs

4:48 i.e. :require … [secretary.core :as s :include-macros true :refer [defroute]])

4:48 ddellacosta: petrust: what happens if you get rid of :include-macros true, does it compile okay?

4:49 petrust: and defroute, since that is a macro

4:49 petrust: that is, only this: [secretary.core :as s]

4:49 petrust: seems to be working…

4:51 ddellacosta: petrust: huh, okay. What about if you then add the macro stuff back in via (:require-macros [secretary.core :refer [defroute]]) at the top of your ns form?

4:52 petrust: added back, compiling…works!

4:52 hmm

4:52 ddellacosta: petrust: weird. I'm not sure what is going on since I just created a brand new project and compiled it just fine w/secretary exactly as you described in your first example.

4:53 I'll try cleaning as you did, see if that makes any difference

4:54 nope, works fine...curious

4:55 petrust: I'm wondering if there's some other wackiness happening in your project.clj, but I'm really not sure what would be causing this. However, if you can get it to work with :require-macros I suppose you're set...

4:56 joelkuiper: Does anyone have any experience with using core.async with the HTTP-kit server? Basically I have some (long running) process ops that return a channel (with the computer value on it when done). I'd like to use the HTTP-kit long-polling trick for sending the responses

4:57 but I'm usure how to proceed; this is what I have right now https://gist.github.com/joelkuiper/d6c03488432f3146d72b

4:59 petrust: ddellacosta: ran lein cljsbuild clean, then lein cljsbuild auto again (with :include-macros), and it seems to work now.

4:59 must be some weird state or env var somewhere

5:00 ddellacosta: petrust: huh, okay, that's good. Sometimes an extra clean will do the trick, no idea why sadly...

5:01 petrust: tried a whole bunch of cleans - can’t replicate the error :/

5:07 borkdude: petrust I had the same kind of error yesterday when I tried to write a macro in clojurescript

5:07 cleaning, restarting, retrying.. at some point it worked

5:14 joelkuiper: https://stackoverflow.com/questions/24549565/using-http-kit-long-polling-with-core-async-channels

6:12 Janiczek: Is there any kind of polymorphism operating on two arguments? I'm creating a game and want to do things like (use-on :egg :pan), (use-on :bucket :cow) - but don't know how to NOT have a huge bloated definition of use-on. I'd like to be able to extend it from elsewhere

6:13 Would multimethods and (use-on [object subject]) instead of (use-on object subject) work?

6:13 Glenjamin: multimethods can dispatch on all arguments

6:15 Janiczek: Glenjamin: care to elaborate?

6:15 Glenjamin: yep, just typing a repl example :)

6:16 Janiczek: Glenjamin: great, thx :)

6:16 Glenjamin: ,(do (defmulti f vector) (defmethod f [:a :b] :a-and-b) (defmethod f [:c :d] :c-and-d))

6:16 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Parameter declaration :a-and-b should be a vector, compiling:(NO_SOURCE_PATH:0:0)>

6:16 Glenjamin: oh right

6:17 ,(do (defmulti f vector) (defmethod f [:a :b] [&_] :a-and-b) (defmethod f [:c :d] [&_] :c-and-d))

6:17 clojurebot: #<MultiFn clojure.lang.MultiFn@28500a>

6:17 Glenjamin: ,(f :a :b)

6:17 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: sandbox/eval56/fn--57>

6:17 Glenjamin: hrm, i guess i need to be more explicit

6:17 ,(do (defmulti f (fn [a b] [a b]) (defmethod f [:a :b] [&_] :a-and-b) (defmethod f [:c :d] [&_] :c-and-d))

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

6:17 Glenjamin: ,(do (defmulti f (fn [a b] [a b])) (defmethod f [:a :b] [&_] :a-and-b) (defmethod f [:c :d] [&_] :c-and-d))

6:17 clojurebot: #<MultiFn clojure.lang.MultiFn@28500a>

6:18 Glenjamin: ,(f :a :b)

6:18 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: sandbox/eval138/fn--139>

6:19 Janiczek: ,(do (defmulti f identity) (defmethod f [:a :b] :a-and-b) (defmethod f [:c :d] :c-and-d) (f [:c :d]))

6:19 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Parameter declaration :a-and-b should be a vector, compiling:(NO_SOURCE_PATH:0:0)>

6:20 Glenjamin: i could have sworn this worked :s

6:21 oh right, it doesn't like my variadic thing

6:21 (do (defmulti f (fn [a b] [a b])) (defmethod f [:a :b] [a b] :a-and-b) (defmethod f [:c :d] [a b] :c-and-d))

6:21 ,(do (defmulti f (fn [a b] [a b])) (defmethod f [:a :b] [a b] :a-and-b) (defmethod f [:c :d] [a b] :c-and-d))

6:21 clojurebot: #<MultiFn clojure.lang.MultiFn@28500a>

6:21 Glenjamin: (f :a :b)

6:21 ,(f :a :b)

6:21 clojurebot: :a-and-b

6:21 Glenjamin: ,(f :c :d)

6:21 clojurebot: :c-and-d

6:21 Glenjamin: ,(f :c :a)

6:21 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No method in multimethod 'f' for dispatch value: [:c :a]>

6:21 Janiczek: nice :)

6:21 thanks a lot!

7:02 silasdavis: I think I've found a bug in: https://github.com/clojure/data.priority-map

7:03 (-> (priority-map-by (fn [[_ x1] [_ x2]] (compare x1 x2))) (assoc :a [:foo 2]) (assoc :b [:bar 2]) (assoc :c [:baz 1]))

7:03 returns {:c [:baz 1], :b [:foo 2], :a [:foo 2]}

7:03 that is, when you use a custom comparator it looks like if two values are equal under comparison they are considered to be the same

7:04 rather than just being sorted as equal

7:05 I was using a priority map for [path-to-node distance] and I was getting path-to-node overwritten in all key-value pairs with the same distance

7:05 where can I report this?

7:06 issues are disabled on that repo

7:06 Bronsa: silasdavis: https://github.com/clojure/data.priority-map/blob/master/CONTRIBUTING.md

7:08 silasdavis: ah thanks

7:09 Bronsa: silasdavis: I'm reading the readme, have you read http://sprunge.us/VXXT this?

7:09 silasdavis: ah

7:09 well done

7:10 and thanks

7:10 Bronsa: np

7:10 silasdavis: that's excactly what I'm doing wrong

7:53 perplexa: hai. is there a way to get the namespace of a function from within the function?

7:54 like (ns mynamespace ...) (defn x[] (resolve mynamespace here))

7:54 TEttinger: ,*ns*

7:54 clojurebot: #<Namespace sandbox>

7:54 perplexa: that doesn't work

7:55 *ns* is the current namespace, not the absolute namespace of a function ;/

7:55 Bronsa: you have to close over the *ns*

7:55 (let [ns *ns*] (defn x [] ns))

7:55 perplexa: i was using *ns* before and it ended up interning functions to the wrong namespace ;p

8:57 Janiczek: hmm uberjar seems not to pack swing with my seesaw project ... is it normal? (when I run it with `java -jar the.jar`, it's OK and sees Swing, but when I bundle it with Ant AppBundler to an .app, it throws NoClassDefFound for java.awt.Window$Type)

8:57 (no expert on Java ecosystem)

9:34 ah, it's probably me (in shell) running java 1.7+ and the system (in the bundled .app) running 1.6 or something. java.awt.Window$Type is from 1.7+ up

9:47 fowlslegs: ,(.rotateRight (long 8) (int 1))

9:47 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: rotateRight for class java.lang.Long>

9:47 fowlslegs: http://docs.oracle.com/javase/8/docs/api/java/lang/Long.html#rotateRight-long-int-

10:00 Bronsa: fowlslegs: it's a static method

10:00 ,(Long/rotateRight 8 1)

10:00 clojurebot: 4

10:12 gfredericks: those sorts of things get made static so they can use primitives amirite?

10:13 Bronsa: gfredericks: probably, yeah

10:30 cbp: arrdem: should the `add examples' page default to 1.4?

10:31 I think it would be more practical to default to the latest no?

10:49 zeebrah: dae know where this moved (out of contrib) http://richhickey.github.io/clojure-contrib/miglayout-api.html ?

10:51 fowlslegs: ,(map #(.bitCount (biginteger (- % 30))) (range 30))

10:51 clojurebot: (4 3 4 3 3 ...)

10:51 fowlslegs: ,(apply list (map #(.bitCount (biginteger (- % 30))) (range 30)))

10:51 clojurebot: (4 3 4 3 3 ...)

10:51 puredanger: zeebrah: afaik it did not go anywhere

10:51 http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

10:51 cbp: zeebrah: maybe you can use this https://github.com/scgilardi/artem

10:52 fowlslegs: ,(.bitCount (biginteger 7))

10:52 clojurebot: 3

10:52 fowlslegs: ,(.bitCount (biginteger -7))

10:52 clojurebot: 2

10:52 zeebrah: puredanger: yeah i saw that page just before

10:52 fowlslegs: Can someone explain what's going on with the java.lang.BigInteger class here?

10:52 zeebrah: cbp: is that maintained? it seems not

10:53 cbp: more recently maintained than clojure.contrib.ma

10:53 fowlslegs: I understand what it means to be in two's complement notation, but it does not specify how many bits it uses as a base.

10:53 cbp: clojure.contrib.miglayout :-p

10:54 fowlslegs: This page http://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html doesn't, that is.

10:54 zeebrah: cbp: it's not the actual miglayout library though, just a coupla useful macros/functions

11:00 fowlslegs: Ahh, it must represent it in two's complement notation in byte multiples. I can finally write my hamming distance function for comparing two BigInts.

12:02 PigDude: when you are sharing core.async code between cljs and clj, does your namespace declaration look like this? https://www.refheap.com/87837

12:02 it seems really ugly

12:03 #+cljs/#+clj everywhere, and the hassle of maintaining two sets of requirements

12:03 *the same set in two places

12:17 Willis1: Hi, I'm investigating the use of The Grinder's support for Clojure:

12:17 http://grinder.sourceforge.net/g3/clojure.html

12:18 But from what I can tell, there's no way to use lein to pull in additional dependencies

12:18 because the Grinder invokes the clojure scripts directly

12:18 Has anybody made any effort to use lein and grinder together?

12:46 synkte: What is the best way to test a function that creates a new row entry into a sql database?

12:46 Is there a lib that could help with that?

12:48 mdeboard: synkte: http://clojure.github.io/java.jdbc/#clojure.java.jdbc/insert!

12:49 synkte: mdeboard: So use the ":transaction?" param?

12:50 mdeboard: synkte: Depends on your particular application

12:50 but if you're asking, the answer is yes

12:51 synkte: Well, the default is true, so no :P

12:52 synkte: mdeboard: So, what would be the best way to test a function that does an insert to a sql database?

12:56 mdeboard: synkte: Insert, then do a select for that value, then delete it if it iexists

12:56 synkte: Do you mean like a unit test i.e. application testing or to only insert if there isn't already a record?

12:57 synkte: mdeboard: unit test

12:57 mdeboard: synkte: Yeah then the way I said there

12:57 synkte: mdeboard: Thank you :)

12:58 mdeboard: no prob

12:58 I bet amalloy_ has some kind of context manager (`(with-row)`)or something that takes care of that cleanup for you

13:01 synkte: mdeboard: That would be awesome

13:03 mdeboard: until then though yeah you'd just have to clean it up yourseff

13:04 synkte: There is this http://clojure.github.io/java.jdbc/#clojure.java.jdbc/with-db-transaction that you could then roll back once done but you'd have to do some additional setup to ensure constraints were not deferred

13:06 13:01 <mdeboard> until then though yeah you'd just have to clean it up yourseff

13:06 13:02 <mdeboard> synkte: There is this http://clojure.github.io/java.jdbc/#clojure.java.jdbc/with-db-transaction that you could then roll back once done but you'd have to do some additional setup to ensure constraints were not deferred

13:06 otherwise you're not actually testing the insert

13:06 just something kinda like it

13:11 dbasch: mdeboard: if I had a unit test for a db I would create a dummy table, insert, and then delete the table

13:11 Janiczek: are immutable bags (multisets) available in clojurescript, or do I have to somehow include mori-bag? (I'm in browser env, not node)

13:15 dbasch: Janiczek: clojure.core doesn't have multisets but there are some libraries around, it shouldn't be hard to adapt one of those for cljs

13:15 Janiczek: yeah, I've found https://github.com/achim/multiset which seams reasonably easy to port

13:16 only protocols and clojure.algo (which I'm not so sure about but maybe it can be bypassed)

13:17 dbasch: Janiczek: as an alternative, you could have a map of keys to counts

13:17 it would be a bit clunkier but at least you wouldn't need an external lib

13:18 of course it might be very inefficient if most of your items appear once

13:18 dave-7: hey, when using om/root to render a site, you pass it a component, an atom and a map. Should the component be re-rendered if I swap! the atom at some point? The basic tutorial seems to indicate so, but I'm not having any luck. Does the atom count as "attached" to a root if you call (om/root some-comp some-atom {:target dom-node})?

13:47 Klaufir: How can I process output from tagsoup ? I have something like this:

13:47 [:html {} [:head {} [:title {} "asd"]] [:body {} [:div {:class "dc"} "text"]]]

13:48 danielszmulewicz: I've been using 'length instead of 'count on sequences, and I could swear it was working all the same. Now I get a runtime error. What gives?

13:48 amalloy: mdeboard: nope, i don't. it also seems a little wonky: don't you want to use the db's transaction mechanism if you're inserting stuff you never want to appear there?

13:48 tolitius: is there a way to require/use from within a function: e.g. in a local scope? https://www.refheap.com/87842

13:49 amalloy: danielszmulewicz: length has never in a million years worked

13:49 danielszmulewicz: amalloy: I'm hallucinating then.

13:49 amalloy: tolitius: no

13:49 dbasch: Klaufir: what do you mean by process? What do you want to get out of that?

13:49 ToxicFrog: danielszmulewicz: .length might have worked, if you were using it on Java objects?

13:49 mdeboard: amalloy: You do, like I said though it requires a little more insight into how constraints are handled inside a transaction, i.e. initially immediate/deferred, not deferred, etc.

13:50 amalloy: ToxicFrog: only on arrays or strings. collections have .size

13:50 mdeboard: that just seemed like a bridge too far to cover w/ that guy's question

13:50 danielszmulewicz: ToxicFrog: No. Just 'length on clojure sequences. I'm utterly confused.

13:50 amalloy: danielszmulewicz: maybe you were using clojure 1.9? the rest of us are still on 1.6, but who knows what future versions will bring

13:51 Klaufir: dbasch: I am looking for the language features to process nestes structures like this. Say I want to get the content for :html/:head/:title

13:51 dbasch: Klaufir: look into things like get-in, or clojure.walk

13:51 danielszmulewicz: amalloy: Hehe, that must be it. I'm with a future version of Clojure.

13:51 (inc amalloy)

13:51 lazybot: ⇒ 136

13:51 Klaufir: dbasch: thanks

13:52 tolitius: amalloy: thx. I have to aot a file, but only need some ns at runtime (e.g. in -main), otherwise they have macros that expand into a "never ending ..", so it would not aot compile unless it is in main. is there a known way to load/see/make visible from within a function instead?

13:54 amalloy: whaaaaa? you've written a macro that doesn't compile, so you want it at runtime? i think you must be confused about something; do you have more specific code that doesn't work?

13:54 more likely, i think, is that you have some def at the top level of a namespace that performs side effects, such as connecting to a database; the solution is to not have side effects at compile-time, but instead to def a delay or a function that is called at runtime

13:58 tolitius: amalloy: yes, you are right, but it is not a def, it is a macro, that, when expands (which happens during compilation), starts a scheduler, hence will work on demand, but not if aot'ed. I am looking for a way to isolate this macro expansion in -main. (yes, I know that macro should be rewritten, but that is a bit more difficult at the moment [different project, different existing dependencies, etc.])

14:00 hiredman: tolitius: if the macro performs side effects at macro expansion time there is no way to isolate that, code is macro expanded before it is compiled and then run

14:00 aot compilation saves the byte code after compiling so you can run it later, but the macro expand has already happened

14:03 tolitius: hiredman: I understand that, what I am looking for is a way to only ever "require"/"use"/"load" the namespace where this macro lives on demand. e.g. compile the file that in main has "… and 'import' this namespace as you're running (e.g. runtime)"

14:04 hiredman: avoiding compiling the namespace with this macro ahead of time

14:05 TimMc: tolitius: It sounds like your desire to do this with a macro is distorting your entire program.

14:05 danielszmulewicz: amalloy: Mystery solved. I was using incanter which advertises a :use namespace usage. This should be outlawed.

14:06 technomancy: ~guards

14:06 clojurebot: SEIZE HIM!

14:06 amalloy: tolitius: i don't know what this macro is, but it sounds like a scourge on this planet

14:07 tolitius: TimMc: it is more of a curiosity now, since I see why it would be useful to do, and now I just want to get to the bottom of whether it is possible (I agree that macro needs to be changed)

14:08 TimMc: (to have a better control of what gets aot'ed)

14:09 TimMc: similar to http://dev.clojure.org/jira/browse/CLJ-322

14:12 Demosthenes_: (doc +)

14:12 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0. Does not auto-promote longs, will throw on overflow. See also: +'"

14:13 Demosthenes_: (doc apply)

14:13 clojurebot: "([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args."

14:19 stuartsierra: All, CLJ-322, old friend. It's been a while. We were so young back then. Where did all the time go?

14:46 danielszmulewicz: I assumed that any library that has 'core in it (like core.matrix) ships with Clojure. Wrong again.

14:47 amalloy: danielszmulewicz: most don't

14:47 core.* is more like "libraries that might one day be part of clojure"

14:47 "...and which also live at github.com/clojure/*"

14:48 danielszmulewicz: amalloy: They're halfway there :-)

14:48 (+ amalloy)

14:48 TimMc: Huh, the phrase "ships with Clojure" is ambiguous -- at first I read it as "includes Clojure as a dependency", not "is included in the Clojure jar".

14:48 danielszmulewicz: (inc amalloy)

14:48 lazybot: ⇒ 137

14:48 TimMc: $karma TimMc

14:48 lazybot: TimMc has karma 60.

14:48 TimMc: Man, I've got some catching up to do.

14:49 danielszmulewicz: TimMc: Don't seat it. amalloy is a bot and everybody knows that.

14:49 *sweat*

14:50 arrdem: no mere human could contribute so much to the channel :P

14:50 Klaufir: Whats the point of 'compare-and-set!' ?

14:51 amalloy: (inc TimMc) ; to get you started

14:51 lazybot: ⇒ 61

14:51 {blake}: Aw, a pity inc!

14:51 * TimMc changes his name to John Henry and starts trying to compete with amalloy

14:51 Janiczek: :

14:51 :D

14:51 amalloy: Klaufir: mostly to implement swap! with. i think i saw one case where it made sense to use compare-and-set! over swap!, but mostly you can ignore it

14:51 TimMc: (dec TimMc) ;; I don't need your pity!

14:51 lazybot: You can't adjust your own karma.

14:51 TimMc: ha

14:51 amalloy: TimMc: largesse, not pity

14:51 Klaufir: amalloy: i see, thanks

14:52 Bronsa: amalloy: swap! is not implemented in terms of compare-and-swap! though

14:52 compare-and-set!*

14:52 amalloy: well, it could have been

14:52 instead, it's implemented in java with an equivalent thingy, compareAndSet

14:53 Bronsa: amalloy: I don't think swap can be implemetned in terms of compare-and-set

14:53 amalloy: really?

14:53 TimMc: Other way around, right?

14:53 hiredman: there are CAS based algorithms where you want better control over the retries

14:53 puredanger: pretty much everything can be implemented in terms of CAS

14:54 hiredman: Bronsa: what makes you say that?

14:54 amalloy: (defn swap!' [a f] (let [old @a, new (f old)] (if (compare-and-set! a old new) new, (recur a f))))

14:54 TimMc: Or... thyey can be implemented in terms of each other.

14:54 hiredman: no

14:54 Bronsa: amalloy: hiredman uhm I'm definitely wrong

14:54 hiredman: swap! retries until the CAS succeeds

14:55 amalloy: TimMc: cas is more primitive. you can't really use swap to implementi t

14:55 hiredman: comare-and-swap! tries once and returns a boolean

14:55 TimMc: I mean at the CLJ layer, if you had one of swap! or compare-and-set! you could write the other without interop.

14:56 amalloy: i don't think that's true

14:56 hiredman: if you look at the literature for high performance queues, you often want to do a cas, and if the cas fails do some exponential back off, or switch to some some other strategy, which swap! doesn't let you do

14:57 TimMc: amalloy: It might require a second atom. :-P

14:57 amalloy: yes, then you could do it, but that's cheating

14:57 TimMc: Well...

14:58 amalloy: actually it's not entirely clear to me how you could do it with a second atom either. coordinating it is non-obvious, and atoms are terrible at coordination

14:59 if you want a solution that works under concurrency

15:02 TimMc: amalloy: It's stupid, but I think it works: https://www.refheap.com/87845

15:03 amalloy: yeah, i was just in the middle of writing that myself. i was thinking it doesn't work because of retries, but of course you're resetting it each time you try

15:03 so it's theoretically okay. but on the other hand it's not guaranteed to ever return, which is a problem that compare-and-set! is not supposed to have

15:04 TimMc: Yeah, that's the tricky bit. :-P

15:06 Ha, interesting -- you can edit a refheap paste to be private, but not back again.

15:06 which is to say it is now at https://www.refheap.com/b08ad02d8bd667abcf364ac65

15:07 tbaldrid_: amalloy: to the original question, I've used compare-and-set! when I want to return the old value, not the new one.

15:07 amalloy: acutally, every time I've wanted a return value from swap! it's always been the old one, and then I have to write swap-old!

15:07 TimMc: tbaldrid_: Might I suggest https://github.com/timmc/handy/blob/master/src/org/timmc/handy.clj#L129

15:08 amalloy: tbaldridge: really, every time? i find the old one useful about as often as the new one

15:08 TimMc: (split-atom! a identity f)

15:09 puredanger: feel free to vote on http://dev.clojure.org/jira/browse/CLJ-1454 re swap-old!

15:09 tbaldridge: puredanger: I think I did ;-)

15:09 puredanger: I know *you* did :)

15:09 tbaldridge: rofl

15:09 amalloy: eg, to reimplement memoize: (defn memoize [f] (let [a (atom {}] (fn [& args] (-> a (swap! update-in [args] (fn [old] (or old (delay (apply f args))))) (deref)))))

15:09 * tbaldridge has a pet peeve with swap!

15:10 amalloy: tbaldridge: your comment may be the only time anyone has ever used nfirst

15:12 TimMc: I mostly use my fn for (split-atom! a first next)

15:12 seangrove: clojurescript: "extend is not currently implemented"

15:12 >.<

15:14 tbaldridge: seangrove: seems like that would be a bit "fun" to implement in a AOT compiled language like ClojureScript

15:15 seeing as it just takes a hashmap of function names to functions.

15:34 seangrove: Uhg, clojure.walk doesn't support records.

15:35 stuartsierra: seangrove: In 1.6 it does

15:36 seangrove: stuartsierra: Hrm, any idea how that translates to cljs?

15:36 stuartsierra: seangrove: no idea

15:36 Does cljs even have clojure.walk?

15:36 seangrove: https://github.com/clojure/clojurescript/blob/master/src/cljs/clojure/walk.cljs

15:36 tbaldridge: seangrove: if you're using the latest CLJS that means port it yourself and send a patch to dnolen_ ;-)

15:36 * seangrove tears up

15:37 seangrove: I suppose I could take a look at it

15:37 stuartsierra: It's easy

15:37 https://github.com/clojure/clojure/commit/2224dbad5534ff23d3653b07d9dc0a60ba076dd7

15:38 seangrove: stuartsierra tbaldridge: Yeah, haven't contributed anything to cljs recently, would be good to bring cljs' clojure.walk up to date

15:45 dnolen_: seangrove: seems pretty straightforward to me, we have the IRecord marker protocol

15:45 seangrove: dnolen_: Yeah, hacking on it locally

15:45 dnolen_: Should I use (satisfies? IRecord form) rather than (instance? IRecord form) ?

15:46 bbloom: seangrove: yes

15:48 dnolen_: seangrove: you should not consider instance? a thing :)

15:48 it's there internally for perf reasons

15:48 stuartsierra: dnolen_: Are you referring specifically to `instance?` in ClojureScript?

15:48 bbloom: it's also anti-modular to depend on concrete types in general

15:49 dnolen_: stuartsierra: yes

15:49 oh oops sorry

15:49 not enough coffee today

15:49 instance? is fine

15:50 was thinking about implements?

15:50 seangrove: instance? IRecord won't work :)

15:52 seangrove: dnolen_: Ok, satisfies? with stuartsierra's change looks like it works. Will check it out a bit more and submit a patch if so

15:54 dbasch: btw

15:54 ,(satisfies? 1 1)

15:54 clojurebot: #<NullPointerException java.lang.NullPointerException>

15:54 dbasch: ^ could be better

15:54 stuartsierra: dbasch: patches welcome

15:55 dbasch: stuartsierra: will look into it

15:58 stuartsierra: dbasch: Ah yes, looks like http://dev.clojure.org/jira/browse/CLJ-1107 again.

15:58 dbasch: ,(instance? nil nil) ;; stuartsierra is there a reason this behavior is desirable?

15:58 clojurebot: #<NullPointerException java.lang.NullPointerException>

15:58 dbasch: ah, ok

16:00 puredanger: dbasch: no, but it's a "breaking" change

16:01 (although the broken things are already broken, imo)

16:01 dbasch: puredanger: oh well

16:02 stuartsierra: (instance? nil nil) throwing NPE does make sense: that's a bytecode op on the JVM.

16:03 null has no type, therefore it is an error to ask for the type of null.

16:04 dbasch: stuartsierra: it does make sense, but does it make more sense than returning false-y?

16:05 stuartsierra: maybe

16:05 sveri: Hi, I am trying to use sente and I can establish a ws connection from client to server, however, when I look at the connected uids atom I only see this: {:ws #{nil}, :ajax #{}, :any #{nil}} and it looks like the connection is ok, but the uid is "nil" which is weird I guess, this is my server and client side code: http://pastebin.com/aahbRDQx

16:05 dbasch: the reason I brought it up is because it's why (statisfies? 1 1) throws the NPE according to the (old) sources I'm looking at

16:07 ah, it's not that

16:08 I think it's this line https://github.com/clojure/clojure/blob/ef2e762e21a817305314ed10bc33505bed6874a5/src/clj/clojure/core_deftype.clj#L497

16:23 tbaldridge: dbasch: yeah, the first argument is supposed to be a protocol. You're handing it a integer, thus by the laws of Clojure anything can happen

16:24 dbasch: tbaldridge: do you think it would be worth checking to return a more meaningful error instead of an NPE?

16:24 arrdem: {:pre [(protocol? ...)]}

16:24 tbaldridge: dbasch: welcome to clojure.....

16:25 dbasch: (inc arrdem)

16:25 lazybot: ⇒ 32

16:25 tbaldridge: dbasch: that requires a check at the invocation of every call to satisfies. Good luck getting that patch approved.

16:26 stuartsierra: I think it's doable as a fall-through case without adding an additional check at the beginning.

16:28 amalloy: stuartsierra: maybe just catch the exception that is actually produced and wrap it in something nicer? iirc a try/catch costs basically nothing if no exception happens, right?

16:29 stuartsierra: amalloy: probably not needed

16:30 arrdem: amalloy: couldn't that obscure other errors?

16:30 amalloy: arrdem: in satisfies? what other error could there be?

16:31 true, false, what-the-hell-is-this-i-wanted-a-protocol are the only three reasonable outcomes

16:31 arrdem: heh

16:31 yeah looking at this I don't see another way to make it explode right off

16:31 dbasch: I just hate NPEs

16:32 arrdem: tbaldridge: I did ultimately manage to rebind ns... had to write my own alter-var-root based with-macro-redefs because with-redefs kills the macro metadata and breaks everything

16:32 amalloy: googled around a bit, and it looks like try/catch is free if nothing is thrown, except that it adds bytecode, and can prevent some optimizations that assume linear control flow

16:32 {blake}: Is there are more succinct way of saying "if (nil? %1) (list %2) (cons %2 %1))"?

16:33 tbaldridge: arrdem: lol yeah, I forgot there's a macro flag on vars

16:33 amalloy: {blake}: #(cons %2 %1)

16:33 the if is pointless

16:33 arrdem: tbaldridge: the fun bit is that using with-redefs on a macro flagged var permanently kills the macro flag, which makes code reloading totally horked :D

16:34 tbaldridge: arrdem: I bet you could do some reflection black magic....

16:34 {blake}: amalloy, Thanks. Thought I tried that but I must've gotten it wrong.

16:34 (inc amalloy)

16:34 lazybot: ⇒ 138

16:34 tbaldridge: arrdem: http://stackoverflow.com/questions/1555658/is-it-possible-in-java-to-access-private-fields-via-reflection

16:34 {blake}: Sorry, TimMc

16:35 arrdem: tbaldridge: sure, but why bother. this works a treat. https://www.refheap.com/87848

16:35 dbasch: OTOH if someone is using protocols (which is not a beginner feature) perhaps an NPE is not that horrible

16:40 TimMc: amalloy: I recently learned that using a finally clause causes code to be duplicated for each catch clause. It's interesting that they chose that instead of using more complicated gotos.

16:41 I'm now imagining some absolutely horrifying situation where a cosmic ray alters the in-memory code for one copy but not another and is even more impossible to debug. :-P

16:41 puredanger: there have been a couple strategies used for try/catch/finally bytecode over the years

16:41 I think it was jdk 6 where it last changed significantly

16:42 tbaldridge: I know try is mostly free in Java, but is it in clojure? Try bodies are anonymous functions last I checked

16:43 Jaood: is there a way to clear/clean the user ns in the repl without restarting it?

16:44 amalloy: i don't think that's true, tbaldridge

16:44 puredanger: tbaldridge: handwave handwave JIT JIT handwave

16:44 amalloy: the body of a try is parsed as a BodyExpr, which emits as just a bunch of statements

16:44 Bronsa: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L2161-L2162

16:45 dbasch: Jaood: you mean something like this? http://stackoverflow.com/questions/3636364/can-i-clean-the-repl

16:45 amalloy: dangit! snuck that in there, apparently. good eyes, Bronsa

16:46 tbaldridge: puredanger: it'd be a interesting thing to try sometime, my repl experiments say no, but yes, jit stuff

16:47 amalloy: can someone explain to me what the various contexts in the compiler mean? i've never really been able to work that one out. like i've seen EXPRESSION and EVAL before, but don't remember seeing RETURN; and anyway i don't know what the others really mean

16:47 Bronsa: amalloy: return means the expression is in return position

16:47 as opposed to statement

16:47 (do 1 2 3)

16:48 1 2 statement, 3 return

16:48 Jaood: dbasch: yeah, thanks

16:48 Bronsa: amalloy: expression is non return, non statement

16:48 amalloy: meaning the expression value is used but it's not in return position. if it's a statement the return value can be discarded

16:49 amalloy: eval is this weird context that's somewhat like expression but used when the code is loaded via eval (usually in the repl)

16:50 amalloy: Bronsa: when is an expression's value used but not in return position?

16:50 Bronsa: amalloy: in a binding for example

16:50 (let [a 1] 2)

16:50 1 is an expr

16:50 2 is return

16:52 amalloy: because it's...returning from the let expr? but that's not necessarily returning from the whole function, right? like, in (let [x (let [a 1] 2)] 3), 1 and 2 are both used but not returned

16:52 but 2 is still in RETURN position because it's being returned from the letexpr, whereas there's no expr that 1 is returned from

16:52 (aside from the ConstExpr that emits it?)

16:54 Bronsa: amalloy: so, wherever you can put a recur, that's a return, if the expression is in do and is not the last expression in that do (do [this]* x), it's a statement, otherwise it's either expression or eval

16:55 in your example 2 has a return ctx, yes

16:56 amalloy: no actually it's an expr. it has to be in a return position of a fn or a loop to be a return

16:57 amalloy: i see. so return is like "this would be in tail position if this were the top-level expr of a loop". so the 2 could be in return context, except that it's being parsed as part of a try that's in eval context?

16:57 er, part of a let-binding

16:57 bracki: How do I turn a java.io.Outputstream into a ring {:body stream} response?

16:58 Bronsa: amalloy: that should be correct, yes

16:59 technomancy: bracki: you can copy it to a ByteArray and then make a ByteArrayInputStream

16:59 Bronsa: amalloy: the last expression in a "block" (let/letfn/..) takes the context of the "block"

17:00 so if the let is in return position (tail-call of a fn/loop/method body) then the expression in tail position in the let body will have return ctx

17:02 amalloy: I suck at explaining it but it's really easy to understand if you play a bit with it, analyze some expressions with t.a.j and look at their (-> ast :env :context) and it'll be clear

17:03 amalloy: yeah, i think i get it, Bronsa

17:04 technomancy: gross

17:04 use a pipe; there's one helpfully included in compojure

17:05 or maybe ring. i'm never quite sure

17:05 technomancy: sure, provided you have control over that

17:05 bracki: technomancy: Like here http://data-sorcery.org/2009/11/29/incanter-webapp/?

17:06 atyz: Hey all... what would happen if you spawned a lot of futures (blocking calls lasting ~1 second each) then enver defererenced them

17:06 *never

17:06 amalloy: technomancy: huh? control over what?

17:06 turbofail: atyz: a future runs whether you dereference it or not

17:07 bracki: There's this https://groups.google.com/forum/#!topic/clojure/BZxYCQQJtV8 and this https://github.com/ring-clojure/ring/blob/bc4ddda43e68cc2117f73306d936555ac870239b/ring-core/src/ring/util/io.clj#L11

17:07 turbofail: atyz: there's a limited thread pool for running them

17:07 bracki: I don't understand the signature of piped-input-stram

17:07 amalloy: bracki: https://github.com/ring-clojure/ring/blob/bc4ddda43e68cc2117f73306d936555ac870239b/ring-core/src/ring/util/io.clj#L11

17:07 puredanger: turbofail: it's not limited

17:08 amalloy: you can't really convert an output stream to an input stream, bracki. it doesn't make sense, because neither of those actually stores data

17:08 atyz: turbofail: I think futures are pulling from an unbound pool

17:08 amalloy: if you have an output stream, and you want writes to it to be sent out over ring, that's what piped-input-stream is for

17:09 atyz: Basically after a while my cpu usage hits 100% and never comes down. I think this could be due to me abusing futures, is this at all possible?

17:09 bracki: But how?

17:09 dbasch: bracki: what is your output stream? where does it come from?

17:09 amalloy: but you still have to actually do those writes, so the idea is (let [response (piped-input-stream (fn [out] (.write out "hello!")))] {:status 200 :body response})

17:10 bracki: I want to use http://people.apache.org/~thejas/thrift-0.9/javadoc/org/apache/thrift/transport/TIOStreamTransport.html

17:10 So I'm not in control of the writing to the outputstream...

17:10 turbofail: oh hm. wonder why i thought it was bounded

17:10 puredanger: atyz: do a thread dump - who's doing the work?

17:11 turbofail: the agent send pool is bounded

17:11 bracki: So I guess what technomancy said applies. Hard to wrap that thing in a function...

17:12 puredanger: turbofail: the send-off and future pool (same pool) is a cached thread pool

17:12 atyz: puredanger: I did a thread dump (https://www.refheap.com/87785) but it looks similar to a new fresh healthy machine and the thread counts weren't all that different

17:12 turbofail: puredanger: ah, the send-pool must have been what i was thinking of

17:13 puredanger: atyz: none of your threads are doing anything. I don't believe your cpu usage is coming from this process :)

17:13 atyz: puredanger: that is really sad news. could you think of anything else that could cause this?

17:13 dbasch: bracki: it's pretty easy to wrap that in a function, but what do you mean you're not in control of the writing to the output stream?

17:13 puredanger: why do you think it's this process?

17:14 atyz: even once the machine is pulled from the LB it continues to stay at 100% utilization

17:14 dbasch: bracki: I mean, you're writing thrift to an outputstream that you gave that class

17:14 atyz: puredanger: my thinking is that there were a bunch of theads getting backed up (they are blocking calls) and for some reason not being killed off

17:14 TimMc: atyz: Good question -- you *have* confirmed that it's the JVM that's eating the CPU?

17:15 puredanger: atyz: there are a few threads reading/waiting on sockets - it's possible one of those is reading vast quantities of stuff in a tight loop, but I'd still guess that's IO bound, not CPU bound

17:15 atyz: blocking threads won't show up as cpu utilization

17:15 atyz: TimMc: I have confirmed that it is the JVM eating the cpu

17:15 TimMc: OK. :-)

17:16 bracki: dbasch: I'm not doing the write but some Java class using this https://github.com/apache/thrift/blob/38b453be5a015b7aaefcd91b4e261e53e0e211c2/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java#L140

17:16 dbasch: bracki: ok, but where is it writing to?

17:16 bracki: Basically I have no control over when (.write stream) is being called

17:16 in .write

17:17 atyz: puredanger: if that were the case I would expect the cpu utilization to come down after some time?

17:17 puredanger: atyz: you could connect with jvisualvm or something like that - it can show you what threads are doing

17:17 atyz: Generally the amount of data would be a couple kb at most

17:17 dbasch: bracki: I got that, but what is the output stream?

17:17 atyz: (thats even a stretch)

17:18 amalloy: atyz: i'm with puredanger, your jvm isn't doing anything at all. the only way it could be burning through cpu would be like garbage collection

17:18 bracki: dbasch: Something I'm passing in here https://github.com/apache/thrift/blob/56a648d0ffc370123c4f1047b72d0d80080a1d9b/lib/java/src/org/apache/thrift/TBaseProcessor.java#L26

17:19 atyz: amalloy: if it were garbage collection, how would I confirm that?

17:19 puredanger: atyz: generally I find if my system is violating my assumptions then one of my assumptions is probably wrong :)

17:19 atyz: And why would it max my cpu indefinitely

17:19 puredanger: I'm sure that I'm wrong in many ways here. Just confused and grasping at straws

17:19 puredanger: atyz: you would see the GC threads in the thread dump. jvisualvm / jconsole can also show you gc activity

17:20 amalloy: puredanger: really? i don't recall seeing a gc thread in that list before, like ever

17:21 puredanger: amalloy: maybe I'm having flashbacks to an earlier time :)

17:21 dbasch: bracki: I guess my question is: you're writing to some place. What is that place? The network? A file? A Byte array?

17:21 amalloy: puredanger: i could be wrong. i use yourkit much more than jstack, and while its thread dumps look just like these it's possible it's filtering out some threads i guess

17:22 atyz: OK so just to dispell my theory completely, having many calls spawned by futures would not exhibit the behavior i'm seeing here?

17:22 bracki: dbasch: I guess a bytearray

17:22 puredanger: atyz: I don't see anything in this stack that makes me think it's related to futures.

17:23 atyz: I don't even see anything using cpu

17:23 atyz: puredanger: is it possible thats because I didn't run it for more than a second or two?

17:23 danielsz`: I want to split a sequence of variable length in three parts, with the last part having the possible remainder. Think columns in a table. What would be the idiomatic way to achieve this?

17:23 amalloy: three equal parts, with leftovers appearing in the third?

17:24 danielsz`: amalloy: yes

17:24 dbasch: bracki: then do exactly what technomancy said: (.toByteArray os) and then create a ByteArrayInputStream from that

17:25 amalloy: https://github.com/flatland/useful/blob/develop/src/flatland/useful/seq.clj#L54 does roughly that, except it looks like the excess goes into the first few rather than the last one

17:25 puredanger: atyz: I don't think I understand what you're doing enough to answer that.

17:27 dbasch: danielsz`: you can use partition-all and then concatenate the last two things

17:27 danielsz`: amalloy: Here's my overkill solution: I partition my sequence, put it in matrix, and take the columns. I figured there must be a simpler way (with built-in fns). But it's not that straightforward as I had thought. At least I can't figure it out,

17:28 alas.

17:28 dbasch: danielsz`: e.g. if you have 20 columns you'll end up with 6-6-6-2

17:28 atyz: puredanger: thats fair, I'll take a look into the garbage collection

17:28 dbasch: danielsz`: concatenate the last two and you'll have 6-6-8

17:28 puredanger: just turn on -verbose:gc

17:29 atyz: Can you think of anything in particular I shoudl look out for?

17:29 danielsz`: dbasch: interesting...

17:29 hiredman: the threads are all blocked in that dump, and if you take another dump they will likelly show as blocked again, so the question is, are they actually blocked, or are they flipping back and forth between blocked (waiting on some thing from a queue) and running, the high cpu usage would seem to indicate the switching back and forth, what kind of logging do you have?

17:30 atyz: hiredman: mostly just request/response logging

17:30 Nothing actually looking at the jvm or its processes

17:31 hiredman: are all the threads doing stuff with datomic?

17:31 puredanger: datomic itself has a lot of logging you can turn on, no idea if that would help here

17:32 atyz: hiredman: I don't think they would be

17:32 I'm sshing into a heatlthy machine to see what the thread dump looks like

17:32 amalloy: that's a cute way to do it, dbasch

17:33 hiredman: if datomic reads data in some kind of single threaded fashion, so all your threads are communicating with the datomic io thread via queues you might see something like this, but that is a stretch

17:35 atyz: https://www.refheap.com/87850

17:36 hiredman: on an inactive machine, they are blocked as well

17:37 puredanger: atyz: when you say you just run it for a second or two, do you mean you start the jvm, see 100% cpu, then kill it? if so, what happens if you let it run?

17:38 atyz: puredanger: Sorry, i meant to say I killed the thread-dump prematurely

17:38 puredanger: well don't do that :)

17:38 arohner: what is the preferred logging lib to use w/ tools.logging?

17:38 puredanger: arohner: prob log4j or slf4j over log4j

17:38 arohner: thanks

17:39 atyz: Before I killed the threaddump. I started teh machine, it was put into the LB. It was used for 2 hours, I pulled it out of the LB (when it was at 100% utilization) and it stayed at 100% utilization for the next 6 hours. At which point it I killed it

17:39 I currently don't have any machines at 100% utilization because we just did a deploy and there is very little usage

17:40 puredanger: so you need a full thread dump when it's at 100% utilization. otherwise, you can't know what's actually using cpu at that time

17:41 atyz: But on monday I am very certain that there will be a few at 100%

17:43 puredanger: is there something I should be looking at in the thread-dump that woudl indicate that its the thread that would be using my cpu?

17:43 puredanger: atyz: it will be RUNNING or RUNNABLE (can't remember which)

17:44 atyz: So if the thread-dump doesn't say either ofthose - the cpu usage is not from any of those threads

17:44 And it would be the GC, possibly?

17:46 puredanger: well, it's not the BLOCKED threads. you had a few in IN_NATIVE which could theoretically be doing something but are usually IO waiting. could be GC. using gc logging should make that obvious or just connect with one of the jvm tools and see where the pools are.

17:48 atyz: Ok, I'll give it a look when I have another machine thats stuck at 100% utilization. thank you puredanger amalloy and hiredman

17:49 puredanger: happy hunting! :)

17:50 atyz: haha, I wouldn't say happy. I hate it when computers make me feel dumb :P

17:50 TimMc: atyz: Is it throughly enough wedged that you can't attach a liverepl?

17:50 cbp: /

17:51 atyz: TimMc: I haven't tried that. they are deployed as jars

17:52 And don't have access to the box in that way.

17:52 That said, despite being at 100% it still seems fairly responsive

17:53 rasmusto_: is there something special I have to do to get leiningen to extract/use native dependencies?

17:54 technomancy: rasmusto_: if the native deps have been packaged for use with lein, there's nothing to do

17:55 rasmusto_: technomancy: not sure if they have. Trying to use lwjgl-platform-2.8.4-natives-windows.jar

17:55 technomancy: unlikely then

17:55 unfortunately the docs for that are pretty much crap

17:55 https://github.com/technomancy/leiningen/issues/1385

17:56 TimMc: atyz: liverepl attaches to a running JVM whether it has Clojure in it or not. (Unfortunately, it leaks a classloader each time, so you don't want to do it a lot.)

17:57 technomancy: protip: don't think of it as crap documentation, think of it as a pull request opportunity

17:58 rasmusto_: technomancy: if I add an explicit dep for [org.lwjgl.lwjgl/lwjgl-platform "2.8.4" :classifier "natives-windows"] it'll pull the jar down, I guess I can see about extracting it somehow

17:59 aperiodic: last time I made an artifact to be consumed as a native dependency I remember writing a bash script that did manual jar surgery

17:59 rasmusto_: powershell, here I come

17:59 technomancy: rasmusto_: if the files that need extracting are under a consistent prefix, :native-prefix "natives/" in the dep vector might do it?

18:01 rasmusto_: technomancy: the dlls are just in the root of the *-platform.jar

18:01 technomancy: rasmusto_: maybe just :native-prefix "" then?

18:02 rasmusto_: kk, will try

18:02 technomancy: !! the exception changed. I think that worked

18:02 danielsz`: If there is a consensus that wholesale imports with :use in the namespace declaration is *evil*, how come the most respected libraries instruct users to do exaclty that? I've seen it three times in a row today. Incanter, core.matrix and ring or ring related. Where is our leadership?

18:03 atyz: TimMc: https://github.com/djpowell/liverepl <--- That?

18:03 technomancy: danielsz`: I'm fairly suspicious of incanter in general

18:04 have run into a number of poor API decisions there, primarily around using macros for no reason

18:04 amalloy: incanter is like a suuuuuuuper old project

18:05 technomancy: danielsz`: also there's a big difference between calling the use function directly and putting a :use clause in your ns form

18:05 amalloy: the author almost has to have been new to clojure when he started, since clojure was new. so probably he's made some poor decisions, in addition to following things that were community standards at the time but have since changed

18:06 * dgleeson discovers destructuring.... refactors whole code base

18:07 TimMc: atyz: That's the one. We usually kill any host we use it on shortly afterwards as a best practice because of the classloader leakage, but it's hella useful for diagnosis or even hotpatching.

18:07 Unfortunately it doesn't have line editing, IIRC.

18:07 danielsz`: amalloy: core.matrix is halfway in the standard library! They should know better.

18:07 technomancy: danielsz`: being a contrib project is entirely a political thing; it doesn't say anything about the code itself

18:08 atyz: TimMc: The machine is basically dead anyway so I'll give it a try! Thank you :)

18:08 I'm going to go home now, enjoy your night!

18:08 technomancy: danielsz`: if anything it means the docs are less likely to be accurate, because they can't take pull requests

18:08 TimMc: same here, you too

18:08 technomancy: for quick fixes like this

18:09 danielsz`: technomancy: What is a use case of a direct use of the use function (except in the README to make a point)?

18:09 technomancy: danielsz`: repl exploration

18:10 danielsz`: technomancy: oh yes, of course.

18:10 technomancy: it's faster to type =)

18:10 danielsz`: James Reeves definitely knows better. I'll tell him when I get the chance.

18:13 ishanc: Is it possible to gen-class clojure code and use it from java code when both the java and clojure code reside in the same maven project

18:13 I am using the clojure-maven-plugin and calling java from clojure works fine, but not the other way around

18:18 bracki: What does this mean? https://github.com/xsc/thrift-clj/blob/master/src/thrift_clj/client.clj#L29

18:18 What is the signature?

18:19 cbp: bracki: what signature? {:keys [protocol]} ?

18:19 bracki: i'm talking abot the & :keys stuff

18:19 cbp: it means you can call that function like (connect! client-class transport :protocol whatever)

18:19 rasmusto_: ,(let [{:keys [a b c]} {:a 1 :b 2 :c nil}] [a b c])

18:19 clojurebot: [1 2 nil]

18:19 cbp: bracki: its map destructuring

18:20 bracki: the & means it groups every arg after it and then the {:keys } stuff means it destructures it as a map

18:21 bracki: and the [protocol] part?

18:22 gfredericks: ,(let [[a b & {:keys [c d]}] [1 2 :e :e :d :d :c :c]] [a b c d])

18:22 clojurebot: [1 2 :c :d]

18:22 gfredericks: bracki: that means the only key it recognizes is :protocol

18:23 danielsz`: (inc amalloy)

18:23 lazybot: ⇒ 139

18:23 danielsz`: That's for the slice function.

18:23 gfredericks: bracki: i.e., you could call this function like (connect! my-client-class my-transport :protocol my-protocol)

18:23 or (connect! my-client-class my-transport)

18:24 bracki: tried that but doesn't work...

18:24 cbp: bracki: it means it's assigning the key :protocol (hence the :keys part) to the name 'protocol'

18:24 radix: I wonder why they didn't just have two different signatures, with with a protocol argument and one without

18:24 cbp: the value of the key i mean

18:24 radix: s/with with/one with/

18:24 gfredericks: bracki: in what way did it not work?

18:25 radix: easier to add more options later?

18:25 radix: yeah, maybe that.

18:25 cbp: radix: i guess they thought it would be more explicit to force the user to use the keyword

18:25 :-P

18:25 rplaca: radix: also folks find that keywords are better at documenting how variable args are used, if they really are optional

18:26 which is basically what cbp said :)

18:27 whodidthis: maybe would be easier to have a map for the opts

18:27 bracki: gfredericks: it always falls throught to https://github.com/xsc/thrift-clj/blob/master/src/thrift_clj/client.clj#L23

18:29 gfredericks: bracki: so what's the first arg you're passing to connect!?

18:29 bracki: Oh noes, overwritten import.

18:29 Everything is fine.

18:29 But thanks for the destructuring bit

18:35 gfredericks: I am having some issue with clojure.test and records/protocols

18:35 something to do with the loading-everything-twice tactic I bet

18:35 cbp: what's up with cider now starting at some 'clojure.test.mode' namespace?

18:35 gfredericks: specifically a record claimed to not satisfy the protocol when it certainly should

18:36 cbp: which, much to my dismay, does not have clojure.repl use'd

18:37 hiredman: cider hates the living

18:39 gfredericks: cbp: I've given up on using things; switched to (ns .)

18:39 hiredman: gfredericks: throw in some aot'ing and you are totally screwed

18:39 gfredericks: hiredman: I'm pretty sure I can avoid that thankfully

18:40 hiredman: in theory if you are just loading everything twice you should be fine, but if you are doing anything at all between the reloads everything will likely break

18:41 if you miss a reload, things will break, if you reload in the wrong order, things will break

18:42 gfredericks: I'm certainly not doing anything other than using normal requires

18:43 maybe it's time to bisect my code until I can isolate it

18:45 hiredman: ah, but do you have :reload in your requires?

18:45 gfredericks: nope

18:45 that would be weird

18:45 hiredman: lein used to stick :reloads in the requires for test namespaces

18:45 gfredericks: O_O

18:45 hiredman: for reasons

18:45 abp: help, i'm bleeding clojure for hours now

18:46 rasmusto_: whatas wrong

18:46 cbp: he's bleeding clojure

18:46 hiredman: when I slip shaving parens get everywhere

18:46 abp: it feels so exciting

18:47 rasmusto_: hiredman: like ~@?

18:48 * gfredericks starts running around his test code with a machete

18:49 abp: cut down maintenance?

18:50 gfredericks: no, figure out why clojure no work

18:51 abp: duh

18:53 amalloy: i like to imagine maintenance is the name of a really old tree in abp's yard

18:57 TimMc: noooo, don't cut it down!

18:58 arohner: has anyone seen 'java.lang.NoClassDefFoundError: clojure/tools/reader/reader_types/Reader' when AOT'ing?

18:59 Janiczek: any thoughts on the coding style / where it's not idiomatic etc. of https://github.com/Janiczek/cook ? (maybe play with the demo first: http://janiczek.github.io/cook/ - it's short but with a bit of reading)

19:00 cbp: I have in cljs (:require [goog.date.DateRange :as DateRange]) and (:import [goog.date DateRange]) and other such things. I'm not sure im doing this right

19:03 danielsz`: (inc hiredman)

19:03 lazybot: ⇒ 49

19:03 danielsz`: That's for the comment on Cider.

19:03 It really does hate the living.

19:03 amalloy: cbp: if you have both of this things and others beside it's pretty likely you're not doing it right

19:04 probably you want only one such thing

19:04 cbp: and.. it's probably wrong since my repl doesn't like it even though the browser does

19:05 gfredericks: okay so here's my setup

19:05 cbp: i guess the answer is to remove the one in the require and switch to DateRange.foo instead of DateRange/foo

19:05 gfredericks: I have three namespaces: protocol, record, and test

19:05 protocol defines a protocol

19:05 record defines a record that implements the protocol

19:06 (and requires the protocol namespace of course)

19:06 the test namespace requires both, and the test creates an instance of the record and calls the protocol fn with it

19:06 and I get an implementation error

19:06 but only with `lein test`

19:06 if I run `lein test :only the-test-ns` then it passes

19:08 cbp: actually nevermind that was due to my namespace declaration in the repl not reloading or something

19:08 * cbp does not understand cljs repls

19:08 amalloy: cbp: Foo.bar is kinda like an escape hatch into plain old js; you shouldn't need to use it

19:09 abp: amalloy: test-maintenance can be a problem. for example testing every single query of an application while also testing the whole api via declarative specs

19:10 amalloy: gfredericks: try putting a (println "compiling x") in each of your namespaces, to see it get double-compiled?

19:10 gfredericks: amalloy: why haven't I done that yet

19:10 cbp: amalloy: but then I need to do (DateRange. x y) (DateRange/foo) and DateRange/some-value, and neither import nor require alone allow me to do all of those

19:11 gfredericks: amalloy: the compile order in the bad case is protocol->record->protocol->test

19:11 in the good case, protocol->record->test

19:11 SO THIS IS GREAT

19:12 * gfredericks goes to make a failing test project in leiningen's tests

19:13 cbp: er actually import might

19:13 le sighs

19:15 * gfredericks fails to reproduce the problem in the test project

19:17 amalloy: interesting, gfredericks. are you sure your tests aren't doing anything weird?

19:17 or your ns forms?

19:17 i say this, as if it were at all useful as a suggestion

19:18 gfredericks: amalloy: the weirdest thing is that the protocol and records are in test namespaces rather than src namespaces

19:18 amalloy: my guess is that I didn't reproduce due to nondeterministic namespace ordering?

19:18 technomancy: gfredericks: maybe try putting them in :source-paths in the :dev profile

19:18 instead of in test/

19:19 gfredericks: technomancy: you're suggesting that test helpers should be separate from the for-realsies-tests?

19:20 cbp: in which i deref an atom and get a core.async exception

19:20 wat

19:20 technomancy: gfredericks: not sure whether that's a general-purpose suggestion or a "this might help in this particular case" suggestion, but yeah

19:21 gfredericks: technomancy: please stay on the line while I try this and a customer service representative will be with you as soon as possible

19:21 technomancy: gfredericks: only if there's decent hold music

19:22 noncom: is there any existing library to get images from google image search ?

19:22 danielsz`: technomancy: I meant to ask you: after writing OCaml code on Grenchman, did you have a moment when you said to yourself, this is it, I'm not going back to Clojure?

19:22 amalloy: cbp: i don't think you can get an exception from derefing an atom, in clojure or clojurescript. you *could* get one from attempting to print the result, or really do anything at all with it

19:23 gfredericks: technomancy: the hold music will be good but it will be interrupted every 47 seconds for a message about how super excited we are to have you as a customer

19:23 noncom: i suppose it is possible with clj-http + some stuff, but probably there is a ready solution

19:23 cbp: amalloy: yes from printing

19:23 amalloy: gfredericks: i hate you now

19:23 gfredericks: amalloy: because of how much I appreciate you as a customer?

19:24 technomancy: it worked

19:24 why do we even need the :reload?

19:24 technomancy: gfredericks: for folks with resident project JVMs

19:25 gfredericks: O_O_O

19:25 * gfredericks can't even figure out what that means

19:25 amalloy: gfredericks: technomancy runs his tests through swank or cider or whatever, not lein test

19:25 technomancy: like if you keep your process up in between task runs

19:25 :eval-in :nrepl, ccw, grenchman, etc

19:26 gfredericks: amalloy: how do I install swank or cider or whatever on my jenkins

19:26 * gfredericks googles for jenkins cider plugin

19:26 amalloy: prolly apt-get. the answer to everything

19:26 gfredericks: where is gtrak

19:26 technomancy: danielsz`: haha, not really. OCaml and Clojure are very complementary.

19:26 cbp: brushing up on his coffeescript

19:27 technomancy: danielsz`: it definitely made me 10x more frustrated at clojure's sloppy nil handling though

19:27 "embrace the platform" is a two-edged sword, as we all know

19:28 amalloy: technomancy: but nils are awesome! 10x zero frustration is still zero!

19:28 technomancy: http://p.hagelb.org/get-out.gif

19:28 gfredericks: lin is an object that signifies the presence of a value; it is always truthy

19:29 the SQL equivalent is called LLUN, and it has the property that LUNN = x is always true

19:29 s/LUNN/LLUN/

19:29 aperiodic: even if x is NULL?

19:29 danielsz`: technomancy: Interesting. I thought there was solace in a native environment vs the hosted one of Clojure (with so many levels of indirectness). And I thought maybe type-oriented development would be addictive. And also more principled design instead of the hackinesss of meta-programming, but maybe all of those are also seductive in their own right.

19:30 gfredericks: aperiodic: don't do that

19:30 technomancy: danielsz`: it also made me realize how little I care about homoiconicity

19:30 gfredericks: technomancy: but but paredit!

19:30 amalloy: aperiodic: testing NULL==LLUN is defined to uninstall your database server

19:30 hiredman: gfredericks: I jave a jenkins plugin that launches an nrepl repl inside the jenkins jvm

19:30 technomancy: danielsz`: the main pain point with ocaml syntax is its precedence rules, not the lack of macros

19:31 rasmusto_: hmm, I have to do a lein clean && lein deps to get my target/native stuff to show up

19:31 hiredman: it was super painful

19:31 the insides of jenkins are terrible

19:31 amalloy: rasmusto_: everytime you run *one* of those commands god kills a kitten

19:31 gfredericks: the insides of _______ are pretty bad too

19:32 technomancy: danielsz`: avoiding the large runtime just means you can apply it to a different class of problems. better at small utilities but worse at long-running servers, etc.

19:32 hiredman: https://github.com/hiredman/jenkins-clojure-injector/blob/master/src/leiningen/jpi.clj

19:32 amalloy: technomancy: i had to run `lein clean && lein deps` a few weeks ago, but this was on lein 1.6 and so i didn't think you'd appreciate the bug report

19:32 technomancy: amalloy: I forgive you.

19:33 rasmusto_: part of my confusion is trying to deal with a project that has a lot of native stuff and non-specific dependencies

19:33 the leiningen stuff is very usable so far, thanks for the support technomancy

19:33 technomancy: rasmusto_: cool

19:33 native code is definitely a weak point right now since no one understands how it works

19:35 danielsz`: technomancy: Maybe if you had written Grenchman in Haskell where precedence rules are configurable we would have lost you for good :-)

19:35 technomancy: danielsz`: lost me to raving lunacy, probably

19:36 arrdem: technomancy: what, you aren't raving already? you built a build tool ffs

19:36 technomancy: debatable

19:36 turbofail: hm. when i have to switch between ruby and clojure i find homoiconicity to be a huge deal

19:37 but perhaps ocaml is different

19:37 technomancy: turbofail: homoiconicity or clarity?

19:37 turbofail: both

19:37 technomancy: clojure achieves clarity/consistency through homoiconicity I would say

19:37 turbofail: i really miss being able to use paredit commands for shuffling my code around

19:37 technomancy: ruby fairs to achieve clarity most of the time, and ocaml achieves it through other means

19:38 also, you can do C-M-k (kill expression at point) without paredit, which goes a long way

19:38 so actually bitemyapp threatened to port grenchman to haskell

19:38 turbofail: ha

19:38 technomancy: haha "Derelict repo, abandoned because I have no interest in making tools for the Clojure community."

19:39 cute

19:39 arrdem: yeah... pls flounce more

19:39 technomancy: https://github.com/bitemyapp/grom

19:39 danielsz`: is it only me or this place feels less threatening since bitemyapp left?

19:40 aperiodic: it's not just you

19:40 arrdem: not just you... it's been an improvement since blocking him on twitter as well..

19:41 last time we met in person he had some one-liner about how he's keeping a scorecard for how many blocks he can accumulate from clojure users...

19:41 danielsz`: amazing how 1 person can set a general mood.

19:41 technomancy: how is this an improvement? https://github.com/bitemyapp/grom/blob/master/src/Main.hs#L29 over https://github.com/technomancy/grenchman/blob/master/grench.ml#L35

19:42 turbofail: hm. how does C-M-k work in ocaml? isn't the entire notion of "next sexp" kind of fuzzy?

19:42 technomancy: turbofail: not at all; it's quite clear

19:43 ttasterisco: so what's the story behind bitemyapp? met him once last year at a clj meetup, he sounded peaceful. fast forward a few months and he moved to haskell and all I saw was some rages at clojure?

19:43 danielsz`: turbofail: Emacs adjusts the meaning of "expression at point" based on context.

19:43 technomancy: at least, emacs is smart enough to figure it out consistently

19:44 amalloy: ttasterisco: from what i understand he's a pretty mellow guy in person. in #clojure, he was abrasive

19:44 arrdem: amalloy: meh... he's way more abrasive online, but he's not exactly mellow in person either

19:44 technomancy: he's out to prove how right slash smart he is

19:45 danielsz`: ttasterisco: He's just an assertive and opinionated person. He discovered Haskell and preaches it now. If you don't mind his style, use it to your benefit. Everybody wins at learning Haskell.

19:45 technomancy: one of my favourite things about OCaml is how it doesn't attract that kind of person

19:46 amalloy: haskell is pretty cool. it's just, knowing that doesn't have to correlate with being a jerk. i don't think haskell was really that important in his decision to leave

19:46 gfredericks: camel-like personalities

19:46 amalloy: technomancy: what is List.tl? clojure.core/rest?

19:46 danielsz`: Haskell are known to be a peaceful bunch too. Bitemyapp is not representative of Haskell any more than he was of Clojure.

19:47 technomancy: amalloy: yeah

19:47 turbofail: technomancy: so when you have something like "|List.fold_left (+) 0 xs", what's the "next sexp"?

19:47 in clojure, depending on where i put the point, the next sexp could be `fold-left', or it could be the whole `(fold-left ...) thing

19:48 but it doesn't seem like i have those options here

19:48 technomancy: turbofail: probably the whole thing. it's been almost a year since I was using it though.

19:48 turbofail: hm

19:50 amalloy: i would have guessed List.fold_left is the next sexp, because in that world you can get the whole thing if you want, via M-4 C-M-k

19:50 technomancy: kinda want to get back into it, but hard to justify when the only clojure I write is lein itself

19:51 I really miss option types and pattern matching

19:52 danielsz`: technomancy: Exactly.

19:53 technomancy: I saw this earlier today. I haven't read it seriously though: http://brehaut.net/blog/2011/error_monads

19:53 technomancy: danielsz`: option types without pattern matching isn't really worth the trouble though

19:54 danielsz`: technomancy: Good point.

19:54 technomancy: there's a big difference between "using this technique in our own codebase" and "this technique is pervasively used in the language"

19:55 danielsz`: technomancy: Very true. Would you say the same for CSP and core.async?

19:55 technomancy: I don't really know enough about csp to comment

19:56 I suspect it's different just because async communication is a much less common need than representing potential failures

19:57 (witness the fact that I have basically never needed the former personally, whereas any nontrivial program needs the latter)

19:58 danielsz`: technomancy: I mean that Lisp languages can adopt paradigms and really sway the constituency, like core.async.

19:59 Lots of people use core.async like it was part of Clojure. While no Option types implementation has convinced. We have the parts. We have core.match and error monads. But it didn't take on.

20:00 technomancy: core.match was horribly broken for years

20:00 danielsz`: Maybe that's the reason. Is it better now?

20:00 technomancy: yeah, but it still never had nearly as much work poured into it as core.async

20:00 which is really infuriating imo

20:00 because it's so much more useful

20:01 danielsz`: I've used it in cljs projects. Very useful, I love it.

20:01 arrdem: tbaldridge: so given that I'm gonna have to eat the price of compiling clojure/core.clj with the reference compiler whenever I finally hook into RT, do you think it's worth the effort to hack the way require behaves so that core.clj is loaded, analyzed and reduced by Oxcart? I'd like to be able to use the tightest core that Oxcart can build but given that RT is gonna build the "normal" core anyway I'm not sure it buys me anything without starting to write m

20:01 technomancy: oh yeah, I speak only for server-side stuff

20:01 turbofail: core.match looks kind of awkward compared to racket's pattern matcher

20:01 syntactically anyway

20:02 brehaut: technomancy: the error monad thing is useful but yes, problematic. i used polymorphism and it works but it makes me sad

20:02 technomancy: i'd rewrite that with core.match in a second if i could

20:02 technomancy: brehaut: erlang just uses pattern matching against lists. works great and is a fairly pervasive pattern

20:02 but core.match is too fast-moving for me to include in lein

20:03 since it would preclude plugins from using newer versions =(

20:03 I've only used core.match in a brief seajure hack night

20:03 brehaut: right

20:04 i think core.match has settled a bit recently? mostly due to some hard problems that dnolen is still working out?

20:04 technomancy: I've been burned by too-old deps several times in the past

20:05 brehaut: it's not just that new versions must be backwards-compatible, it's that new versions literally cannot be loaded by plugins =\

20:05 brehaut: youch yeah

20:06 technomancy: https://github.com/technomancy/leiningen/issues/1563 =(

20:06 gfredericks: technomancy: just renamespace the libs you want :P

20:07 technomancy: ._.

20:07 gfredericks: hey man, do it for leiningen.

20:07 (ns leiningen.clojure.core.match ...)

20:07 brehaut: technomancy: :S

20:08 technomancy: http://p.hagelb.org/10no.gif

20:09 brehaut: haha

20:11 danielsz`: What makes or breaks compatibility with leiningen? Is it only version clashes with leiningen's own dependencies?

20:12 technomancy: danielsz`: plugins can only introduce new dependencies, not new versions of existing ones.

20:13 which I guess is what you said

20:14 danielsz`: I think so. And those existing dependencies are those listed in leinignen's project.clj: https://github.com/technomancy/leiningen/blob/master/project.clj

20:14 Very few dependencies.

20:15 Ah, yes, core.cache gave some trouble

20:16 technomancy: http://p.hagelb.org/lein-deps-tree.html 66 deps in the full tree

20:17 danielsz`: Oh, I see.

20:17 technomancy: data.xml and apache http-client are another source of troubles

20:18 danielsz`: Ah, yes, http-client, talking about fast-moving...

20:19 Shayanjm: If I wanted to run a function, wait for some time, then recur indefinitely - how might I do this without committing code suicide?

20:20 danielsz`: Shayanjm: Would this help? https://github.com/joegallo/robert-bruce

20:21 Shayanjm: why yes, yes it would danielsz`

20:21 thanks :)

20:21 rurumate: is there any source on how to convert the result of (go 42) to a java.concurrent.Future or something similar

20:22 in java preferably

20:22 _99hats_: danielsz: nice find! I've been looking for something like that too

20:22 brehaut: ,(class (future 1))

20:22 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

20:23 brehaut: &(class (future 1))

20:23 lazybot: java.lang.SecurityException: You tripped the alarm! future-call is bad!

20:23 danielsz`: Shayanjm: That's a library solution. Many ways to achieve this with built-in fns too. Look at delay, future, etc.

20:23 brehaut: le sigh

20:23 ,(source future-call)

20:23 clojurebot: Source not found\n

20:23 Shayanjm: much appreciate danielsz` :)

20:23 appreciated**

20:23 danielsz`: Welcome.

20:31 tuft_: is there a way to make certain functions available in all namespaces for repl sessions?

20:31 keep needing to "cd" back to user for doc, refresh, etc.

20:32 technomancy: tuft: not really; the best way to do stuff like that is to expose it from the editor

20:32 cider for instance has doc, source, etc, but it makes adding new commands difficult

20:33 tuft: ah hrm, ok

20:33 thought there might be a way to "patch" clojure.core or something

20:34 my workflow is to run files in the repl, which changes the ns

20:34 arrdem: tuft: not really, you'd have to hack either the namespace macro or in-ns, neither of which is an awesome idea.

20:34 tuft: (i'm using cursive)

20:34 ok, thanks

20:35 technomancy: gfredericks: did you notice how I helped with your defrecord problem without ever once chastising you for using records?

20:36 rurumate: not sure if this works: https://www.refheap.com/87852

20:36 can just call macros using RT.var() ??

20:36 lazybot: rurumate: Uh, no. Why would you even ask?

20:36 technomancy: tuft: a better solution would be https://github.com/technomancy/nrepl-discover

20:36 except it's kinda half-baked

20:37 rurumate: let's be nice lazybot mkay

20:39 amalloy: rurumate: well, he was right

20:39 and robots can afford to be rude

20:40 rurumate: RT.var("clojure.core","->").invoke(5)

20:40 don't know how to write that in a repl so not even trying lol

20:41 amalloy: rurumate: calling macros from java is basically impossible; you can do it, but all they produce is clojure code, which does you no good

20:41 noonian: ,#'->

20:41 clojurebot: #'clojure.core/->

20:41 rurumate: so what call RT.var("clojure.core","eval").invoke("(-> 5)") maybe?

20:41 amalloy: the core.async macros like <! are even worse, because they don't actually exist as real macros: they're just placeholders that go looks for

20:43 rurumate: is <! a macro?

20:43 arrdem: yep

20:43 amalloy: no, it's magic

20:43 arrdem: (assert (magic? macros))

20:43 rurumate: well it could be a function for instance, or just data

20:43 a symbol?

20:43 amalloy: it's none of those things. it doesn't exist

20:44 core.async/go looks for it in your code

20:44 rurumate: since we're in a go block it doesn't matter what it is right

20:44 rplaca: well, it *is* a symbol

20:44 rurumate: so just a symbol? but I had to require it

20:45 rplaca: but the go block macro expansion recognizes it and transforms around it

20:45 rurumate: anyway how to convert the return value of a go-block to a Future<Object>, there surely is something yet?

20:46 just for interop goodness

20:47 noonian: you could write it in clojure and just call that var

20:47 rurumate: uuh, that fn you mean?

20:47 noonian: yes

20:47 rurumate: thatt would work, provided we have already written it in clojure :D

20:47 noonian: go-blocks return channels that return the last form of the body of the go-block

20:48 rurumate: yes, but there is no java interface "channel" and it can be treated like a Future in manyn cases, to from java perspective, it is a Future right?

20:49 sorry keyboard is falling apart

20:49 technomancy: amalloy: I wonder if it qualifies as a special form

20:50 iirc thrown? in clojure.test is the same way

20:50 amalloy: technomancy: well, compare to catch and finally in a try

20:51 rurumate_: I mean we should probable also write a converter channel -> Queue and a new interface Channel maybe but for now I'm trying to convert the ch to a Future

20:51 technomancy: amalloy: yup

20:51 amalloy: try is a special form, and it dictates how to handle catch/finally, neither of which are themselves special

20:51 technomancy: if you consider the macro the "compiler" I think it fits the definition

20:52 rurumate_: how to evaluate whole clojure expression given as string, from java?

20:53 RT.var("clojure.core",:eval read-string can do

20:54 sigh, RT.var("clojure.core","eval").invoke("clojure.core","read-string").invoke("(-> 5)")

20:57 amalloy: rurumate_: in clojure 1.6, clojure.java.api.Clojure makes that slightly more convenient, but you've got the basic idea

20:57 rurumate_: still wrong tho

20:57 amalloy: oh? did you forget to require clojure.core?

20:59 rurumate_: why is this so hard?

20:59 technomancy: because it's java

21:00 amalloy: i don't know what he's complaining about. the thing he pasted works

21:00 ,(-> (RT/var "clojure.core" "eval") (.invoke (-> (RT/var "clojure.core" "read-string") (.invoke "(-> 5)"))))

21:00 clojurebot: #<CompilerException java.lang.RuntimeException: No such namespace: RT, compiling:(NO_SOURCE_PATH:0:0)>

21:01 amalloy: ,(-> (clojure.lang.RT/var "clojure.core" "eval") (.invoke (-> (clojure.lang.RT/var "clojure.core" "read-string") (.invoke "(-> 5)"))))

21:01 clojurebot: 5

21:01 technomancy: well, I wouldn't know how to do that in java

21:01 amalloy: it's what he pasted

21:01 oh, except he needs to cast to IFn

21:02 no, i guess he doesn't. dunno what was wrong for him

21:08 gfredericks: technomancy: no I did not notice that. thank you for helping me with my defrecord porblem

21:08 (inc technomancy)

21:08 lazybot: ⇒ 116

21:08 technomancy: I was holding back

21:10 gfredericks: technomancy: I'm curious how you would model the problem; can't splain it right now though

21:13 technomancy: I guess it's just an unqualified "multimethods" eh?

21:13 arrdem: happy 4th people

21:13 murica

21:29 technomancy: gfredericks: if it's a legitimate polymorphism need, sure

21:29 *legitimate non-bottleneck polymorphism

21:31 gfredericks: technomancy: I use component and I like how protocols formalize the relationship between different parts of the application

21:32 and make it easy to mock stuff in tests

21:32 Shayanjm: not sure if this function does what I want it to do...

21:32 https://gist.github.com/shayanjm/383b5847738c35f748a6

21:33 Basically, when I pass a function into infinite-loop-on-realization, I would like it to execute the function, wait for it to return, and then repeat without blocking the execution of anything else

21:34 hiredman: uh

21:35 realized? is always true for a promise you have delivered to

21:35 Shayanjm: Even if the promise hasn't fully resolved yet hiredman?

21:35 i.e: if 'func' takes like a minute to fully execute

21:35 is current-promise realized before func finishes executing?

21:36 hiredman: Shayanjm: you are calling func as an argument to deliver, so by the time deliver runs, func as already finished

21:36 (while true (func)) is equivilant to what you have written there

21:37 Shayanjm: Oh I see

21:37 So I actually don't even need the when

21:37 I just loop after deliver?

21:38 hiredman: no, the promise and the deliver are doing nothing there

21:38 (while true (func)) will run exactly the same

21:38 Shayanjm: oic

21:38 Okay let me ask this a different way

21:38 given a function which I would like to execute continuously without blocking, and loop on return, what's the easiest way to do that?

21:39 since I'm assuming (while true (func)) will block

21:39 hiredman: Shayanjm: rigth, and so will your code

21:39 Shayanjm: Okay let me try refactoring this really quickly

21:46 hiredman: https://gist.github.com/shayanjm/d37b5b34b08281fa0aa7

21:46 threw the function into a future

21:47 waiting until the function finishes executing, then recurs

21:54 Yeah I don't think this is doing what I want it to do...

22:06 hellofunk: i'm trying to find the best way to architect a series of source files that communicate via async channels; but they must all know the same channel object to do so. to avoid circular dependencies, i'm giving each one an atom, then a controller source file creates the channel and each file gets a copy of it. but seems like potential for state mess

22:08 ddellacosta: hellofunk: why can't you put the shared channel in one namespace, and then include that in all the other namespaces that need it?

22:09 hellofunk: ddellacosta: but just including a namespace isn't the same as including the data in an atom stored in that namespace, right? wouldn't all the includes lead to different default values for the atom?

22:09 ddellacosta: hellofunk: or is that what you're doing and I'm not understanding your question?

22:10 hellofunk: it doesn't have to do with namespaces, it has to do with threads and the type of construct you choose to use

22:10 hellofunk: I like Arthur Ulfeldt's answer here: http://stackoverflow.com/questions/9132346/clojure-differences-between-ref-var-agent-atom-with-examples

22:11 hellofunk: ddellacosta for example, i have a (def a (atom 0)) in a namespace. now I include this namespace in a bunch of others. But if the atom is swapped by one file, that wouldn't mean that the other files that include the atom file will see that new atom's state

22:11 ddellacosta: hellofunk: yes. So you have to know that that's the model you want to use.

22:12 hellofunk: ddellacosta: you mean "yes" as in, I am correct, the swapped atom would not in that case be seen by other files.

22:13 ddellacosta: hellofunk: no, it would. You are updating that atom and that update would be visible to all namespaces using it.

22:13 hellofunk: sorry if I responding confusingly, I meant, "yes it would update"

22:14 hellofunk: ddellacosta: oh that's interesting. I thought that when a file does a require, it basically reads the source file as if it was brand new and hadn't been loaded before and any (def a (atom...)) creates a new atom; therefore every require in the whole project would be creating new atoms

22:15 nathan7: hellofunk: namespaces are like, actual objects

22:15 hellofunk: held in a global table of all namespaces

22:15 hellofunk: they're loaded once

22:16 hellofunk: if you're AOT compiling, they're just classfiles

22:16 hellofunk: nathan7, ddellacosta: ah! so no matter how many times you load (require) a namespace, it really only exists once, including any defs (atoms) it has? wow this is definitely not what I thought was happening.

22:16 ddellacosta: well, think about defonce

22:16 nathan7: hellofunk: yep

22:16 hellofunk: see (all-ns)

22:16 ,(all-ns)

22:16 clojurebot: (#<Namespace clojure.uuid> #<Namespace user> #<Namespace clojure.core> #<Namespace sandbox> #<Namespace clojure.repl> ...)

22:17 hellofunk: nathan7 well this certainly makes things easier. i was forging into spaghetti and now i see that was unnecessary

22:17 nathan7: ,(->> (all-ns) (map #(vector (.name %) %)) (into {}))

22:17 clojurebot: {user #<Namespace user>, clojure.core.protocols #<Namespace clojure.core.protocols>, clojure.core #<Namespace clojure.core>, sandbox #<Namespace sandbox>, clojure.uuid #<Namespace clojure.uuid>, ...}

22:18 nathan7: that map exists somewhere, the global namespace table

22:18 hellofunk: nathan7 so the first namespace to require another namespace "instantiates" it, while any other requires just "point" to it

22:18 nathan7: hellofunk: yep

22:19 hellofunk: you could consider all the namespaces as 'already there', but just lazily loaded

22:19 hellofunk: nathan7 i was so wrapped up in the functional nature of how clojure works, it did not occur to me that this object-oriented type of state could be happening

22:19 ddellacosta: hellofunk: yes, I was going to say, think about defonce--its existence tells you a lot about how namespaces work in Clojure

22:19 (doc defonce)

22:19 clojurebot: eval service is offline

22:20 ddellacosta: $&!#&!

22:20 &(doc defonce)

22:20 lazybot: ⇒ "Macro ([name expr]); defs name to have the root value of the expr iff the named var has no root value, else expr is unevaluated"

22:21 hellofunk: ddellacosta but if require points to existing namespace objects already, i would think that just plain ol' def would not get recreated if what nathan7 says is correct, that def would not re-def everytime the file is loaded

22:21 nathan7: hellofunk: it would re-def every time the file is loaded

22:21 hellofunk: however, the file is loaded only once

22:21 hellofunk: unless you require it with :reload

22:22 hellofunk: nathan7 ah, so if i have a (def (atom ...)) then indeed every time that namespace is required, the def will indeed be reset. thus, defonce would prevent this and ensure that only one piece of state existed unchanged no matter how many requires

22:22 nathan7: hellofunk: no

22:22 ddellacosta: hellofunk: not required, reloaded

22:23 hiredman: require loads the namespace if it is not already loaded

22:23 nathan7: hellofunk: require looks like (if (contains? namespaces) (get namespaces ns) (load ns))

22:23 hellofunk: well, i mean the :require in the (ns at the top of the file.

22:23 nathan7: hellofunk: yes

22:23 hellofunk: it'll load it if it isn't loaded yet

22:24 hellofunk: so, going back to ddellacosta original suggestion, i could put all my shared atoms in a single namespace, but they should be defonce for all of them

22:24 hiredman: ugh

22:24 terrible

22:24 how about you just pass arguments to functions

22:24 hellofunk: hiredman, well this gets back to my original question

22:25 hiredman, the problem is circular dependencies.

22:25 nathan7: hellofunk: even just def would be fine

22:25 hiredman: hellofunk: it isn't

22:25 nathan7: ,@#'clojure.core/*loaded-libs*

22:25 clojurebot: #<Ref@7643fa: #{clojure.core.protocols clojure.instant clojure.java.io clojure.repl clojure.string ...}>

22:25 hellofunk: nathan7 you say that because everything is loaded at once, therefore all the multiple defs just happen at the same time

22:25 hiredman: create a namespace foo, it requires the other namespaces and calls functions from them

22:26 nathan7: hellofunk: http://sprunge.us/YOTZ?clojure

22:26 hellofunk: src/clj/clojure/core.clj around line 5475

22:26 hiredman: (require '[foo.bar :as foo] '[a.b :as a]) (let [c (chan] (foo/bar c) (a/bar c)) etc

22:27 nathan7: hellofunk: if you haven't passed :reload, and it's already loaded, it'll just grab it from *loaded-libs*

22:27 hiredman: global atoms in a namespace? what are you guys even thinking?

22:27 nathan7: q=

22:28 hellofunk: hiredman so you are suggesting to just pass the channel as arguments instead of sharing it in a piece of state

22:28 ddellacosta: hiredman: I've had cases where global atoms are the right solution--for example if I need initialization of a resource to happen at a specific time, and I know it won't change.

22:28 hiredman: hellofunk: yes

22:29 nathan7: my main clojure app has an agent like this for similar reasons

22:29 hellofunk: hiredman well I can't really argue with that. but part of this model is stemming from the fact that I'm using Om, which uses a single global atom for state. and i'm trying to interact with it from various source files

22:29 nathan7: it's the state everything operates on

22:29 hiredman: nathan7: ugh

22:29 nathan7: hiredman: it's a server, it has one global piece of state I need to interact with everywhere

22:29 hiredman: nathan7: ugh

22:29 nathan7: hiredman: if there is >1 instance of it everything is fucked

22:30 hiredman: and I need access to it from nREPLs etc

22:30 hiredman: I'm considering moving it into the file with my -main and passing it to everywhere from there

22:30 hiredman: but that's still kind of painful

22:30 hiredman: like, I am totally with you on this

22:31 hiredman: but this is just like, say, the global table of namespaces

22:31 hiredman: because it's basically this app's namespaces of domain data

22:32 I still have to think a bunch about how the state works for this thing though

22:32 hellofunk: hiredman or i guess one could just pass the atom itself around in the arguments

22:33 hiredman it just seemed easier to reduce lots of extra args on every function

22:33 ddellacosta: hellofunk: I think an atom is a perfectly reasonable place to put a channel that you know won't change for the lifecycle of the app

22:33 hellofunk: but opinions may differ

22:33 nathan7: ddellacosta phrased what I was trying to say perfectly

22:34 like, passing this around everywhere would lead to state being strewn all over the place

22:34 and I'm writing Clojure because I wish to avoid that

22:34 hellofunk: ddellacosta regarding defonce vs just def seems this is useful only if you might actually call def on something more than once

22:35 nathan7: I use defonce for this because I'd rather not have all my state reappear when I re-evaluate the file it's in

22:35 hellofunk: nathan7 be "reappear" you mean get reset to the default state noted in the source file

22:36 nathan7: hellofunk: which is 'empty'

22:36 hellofunk: (defonce world (agent (WorldState.))

22:37 hellofunk: nathan7 so i think you mean "disappear" upon re-eval rather than "appear" ?

22:37 ddellacosta: nathan7: yes, passing stuff around exclusively can lead to equally hard-to-reason-about code

22:37 nathan7: err, disappear, yes

22:37 gfixler: Is there a version of drop-while that returns the result of the predicate test, instead of the shorter collection?

22:37 nathan7: Clojure namespaces are a really pleasant mechanism for this stuff

22:38 hellofunk: well all this has been quite enlightening. all this time i thought :require statements were giving each source file its own copy of everything in the :require'd namespace. fantastic to hear that's not the case.

22:38 ddellacosta_: hiredman: can you please allow my handle (ddellacosta) access to clojurebot?

22:38 nathan7: namespaces just… magically reify a concept I already use in any module system

22:38 and it's grand

22:39 like, my code is data, and it's state

22:39 hellofunk: that namespaces are basically an object-oriented structure inside any clojure project is pretty cool, actually.

22:40 ddellacosta_: hellofunk: not object-oriented. ;-)

22:40 nathan7: object-oriented in the sense that they are objects that can be manipulated, perhaps

22:41 hellofunk: nathan7 object-oriented in that they are single copies of everything they contain, where all the defs are like stored state made available to any other namespace that uses it

22:43 nathan7: hellofunk: I suppose they're actually quite OO

22:43 hellofunk: they're state and behaviour

22:43 gfixler: Nevermind, found it: (some #(when (pred? %) %) coll) ; Clojure is cool

22:43 nathan7: gfixler: hm, there should be a better way

22:43 ddellacosta_: nathan7: but not encapsulated; there's no data hiding, no?

22:43 nathan7: ddellacosta_: ^:private

22:44 ddellacosta_: nathan7: hmm, fair point, although there's a good amount of debate over use of ^:private

22:44 gfixler: nathan7: how about (winner pred? coll)? :)

22:45 danielsz`: gfixler: that reads like 'filter to me

22:45 gfixler: danelsz: you're right - so maybe (first (filter pred? coll))

22:46 nathan7: okay now I feel very stupid for not thinking of that

22:46 gfixler: It's worse for me; I've been looking at this for about 20 minutes :(

22:46 nathan7: this is the thing about functional programming languages

22:47 danielsz`: give it some time. it sinks in and becomes second nature

22:47 nathan7: like, once I start doing complex objects I can just worry about how my shit fits into this complicated structure

22:47 and I can avoid solving actual, well, math, technically

22:48 gfixler: Even though I'm a newb to FP, it's happening. It's becoming more normal each day.

22:48 nathan7: I'm a functional JS programmer, people pay me money to write JavaScript

22:48 and I love it

22:49 gfixler: Nice. I'm in games - mostly Python for tools/pipeline stuff in Autodesk Maya.

22:49 nathan7: because they're convinced that I'm writing JS, and I'm just writing functional code, that happens to be encoded as JavaScript

22:50 and JS lends itself perfectly to this

22:50 clojurebot: It's greek to me.

22:50 gfixler: Hehe. I'm also doing somewhat functional things in Python, and no one is the wiser.

22:50 nathan7: something I've been doing for a few projects is just prototyping the concepts in Clojure

22:50 and then transliterating it

22:50 gfixler: Are you on Linux?

22:50 nathan7: Yep

22:50 gfixler: nice

22:50 nathan7: like, I have a bunch of little helper libs

22:50 gfixler: same here - I can hop in and out of languages instantly

22:51 "How would I do this in Clojure?" - seconds later hammering away in a repl

22:51 then I go back to Python and sigh, because it's much harder there

22:51 nathan7: I wrote a helper lib that's just all the hashmap functions from Clojure

22:51 like, assoc/assoc-in/dissoc/keys/vals/etc

22:51 gfixler: cool - FP is giving JS a second life

22:52 nathan7: and each of the mutation functions has a matching one postfixed with M

22:52 which actually mutates objects in place instead of copying them completely for every operation

22:53 I write my stuff using the pure functions

22:53 gfixler: You didn't reimplement Clojure's shared structure stuff, did you?

22:53 nathan7: I did not

22:53 gfixler: phwew

22:53 nathan7: it's a naive copy

22:53 gfixler: that would be crazy

22:53 nathan7: there's a lib, mori, that just re-exports all ClojureScript's stuff to JSland

22:54 but I want to work with just raw JS objects because mori is giant

22:54 once I'm done writing my logic

22:54 I go through my code and look at where state enters and leaves

22:54 gfixler: Ah, swannodette, I should've known

22:54 that guy is brilliant

22:54 nathan7: and append an M to function calls

22:55 like, same thing you'd do in Clojure with transients

22:55 gfixler: I haven't heard of transients yet

22:55 Well, I guess that's now technically untrue

22:56 nathan7: so, Clojure data structures are like all structure-sharing and stuff, so creating new ones instead of mutating in-place is fast

22:56 but if you're doing, say, group-by, and just modifying the same hashmap a hundred times, you're creating a hundred objects and letting them be GC'd again

22:57 so instead, you do (transient {}), and use assoc! instead of assoc

22:57 and get an object that actually mutates in-place

22:57 gfixler: got it

22:57 nathan7: they implement IEditableCollection

22:58 so, assoc! returns a new transient, and marks the old one as being unusable (every operation on it throws, I think), and you pass them around inside your function the same way you'd do otherwise

22:58 gfixler: interesting

22:58 nathan7: and when you're done with it, you call persistent! and it turns it into a regular hashmap

22:59 gfixler: sweet - I just found this possibly related thing tonight: http://z.caudate.me/you-took-3-months-to-write-a-mutable-array/

22:59 nathan7: like, check (source group-by) in your REPL

23:00 gfixler: like, mutable state creates huge trouble for applications

23:00 gfixler: but functions mutating something internally, not externally visible -> "if a tree falls in a forest, and nobody is around to hear it"

23:01 -> if a function mutates a structure internally, and nobody's around to see it

23:01 gfixler: Right, as with loop invariants

23:01 things are free to change inside the loop, but must be stable at the start and end of each iteration

23:01 nathan7: Yep.

23:07 dbasch: nathan7: I don't think that's correct (assoc! may return the same object, although there are no guarantees)

23:25 nathan7: dbasch: oh?

23:25 dbasch: hmm, yes

23:26 dbasch: e.g.

23:26 ,(let [a (transient {})] (= a (assoc! a :b :c)))

23:26 clojurebot: true

23:28 nathan7: dbasch: identical? would be more clear, but yeah

23:28 (I'm aware transients don't do actual deep equality)

23:29 dbasch: ,(let [a (transient {})] (identical? a (assoc! a :b :c)))

23:29 clojurebot: true

23:32 dbasch: nathan7: other than that, I like your explanation

23:33 nathan7: dbasch: I basically pull the same tricks in JS

23:34 dbasch: like, perform escape analysis in your head, add some M's in places

23:37 dbasch: I'm a compiler nerd (though a fairly half-assed one), so I spend a lot of time thinking about this kind of thing

23:38 dbasch: I have a pile of notes on a fully-refcounted language, where every heap object has an atomic refcounter

23:38 dbasch: and then using that to mutate objects in place opportunistically

23:39 dbasch: and avoiding a lot of allocation using this

23:39 dbasch: and smart ahead-of-time escape analysis style trickery to do even more magic like this

23:40 dbasch: sounds cool, but at the same time a lot of work

23:41 nathan7: like, every time I have to think about this, I go scribble in my notes for a bit on how the compiler could do it for me

23:41 a lot of abstractions can be zero-cost

23:43 and all of these things are incremental — you have a little more information on how the program works, the compiler can do a bunch more

23:43 like, a system I admire very much is ZFS, which has this magical property too

23:43 you throw more hardware at it, and it magically becomes faster, in ways that are actually really intelligent, but a lot of it is emergent behaviour

23:44 I haven't found a word or a good way to describe this concept

23:45 lisps are helping me a lot in this, because in a hundred lines of code I can build another lisp

23:45 and in like, maybe two hundred lines I can do it in any nice language

23:46 so I can build entire languages around single concepts very quickly

23:46 and each time I understand more, and my understanding becomes more abstract

23:47 dbasch: reminds me of this: http://www.buildyourownlisp.com/

23:47 nathan7: yeah, I saw that

23:47 I still want to build one in Rust so I can do stuff like the refcounting lang

23:48 but I have several implementations of my f-expr lisp which are all cool in their own way

23:48 the one issue I have with writing lisps in lisps is that the lines are blurred easily

23:48 I have an implementation of my fexpr lisp, Plan, in Clojure

23:49 and I'm very confused about how it actually works now because I have a hard time telling what is my stuff, and how it works with Clojure stuff

23:50 because I'm doing a lot of voodoo that unites the worlds of Clojure and Plan

23:50 and I don't actually have debugging tools at all

23:50 so I have a null pointer exception somewhere that I can't really debug

23:51 and my mental model of it all is very murky

23:56 dbasch: maybe I should actually follow the buildyourownlisp sometime, but in Rust

23:56 dbasch: I guess it shouldn't be that hard to do it in Go either

23:57 nathan7: Yeah, I have a very strong dislike of Go

23:58 bnoordhuis (possibly drunkenly) perfectly described it as the language that "missed the last 20 years of computer science"

23:58 dbasch: to me it's just another language, neither here nor there

23:58 nathan7: it's neither here nor there indeed

23:58 serjeem: it makes me sad that in TYOOL 2014 they're still putting out non-polymorphic typed languages

23:59 nathan7: elaborate

23:59 oh, nvm, makes sense now

23:59 * nathan7 should think, then type

Logging service provided by n01se.net