#clojure log - May 21 2015

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

0:07 WickedShell: When calling a java object from clojure will the java object update its internal state correctly and retain the same reference from clojure?

0:21 andyf: WickedShell: The Java object will update its internal state the same way it would if the method were called from Java.

0:22 Not sure what you mean by 'retain the same reference from Clojure'. Any reference you have to the object in Java or Clojure code will still be a reference to that object after the method call.

0:42 WickedShell: andyf, it's possible I'm tripping over my own feet here, all I could think of to explain the behavior I'm seeing (calling a function that updates the internal state will never seem to update) might be a different problem though

0:43 andyf: Is it a tiny example, or something that is easily demonstrated?

0:44 Also, do you know for a fact that the Java method is being called from the Clojure code?

0:44 laziness in Clojure can make you think some code should be executed, but it is not until later, or never.

0:45 WickedShell: running the code from the repl, so I'm pretty sure it is, but the only indication is the return value not being null after having been updated with enough bytes

0:47 andyf: are their methods on the Java object that can show you some of its internal state that should be changing?

0:47 s/their/there/

0:49 WickedShell: andyf, http://pastebin.com/m9dANmCw the first bit is some hacked together clojure, where the doseq only ever prints nil rather then returning an object, and then the java code that works on the same java code is below (which works)

0:49 totally believe I'm doing something wrong

0:50 andyf: mavlink_parse_char should be called with a sequence of bytes, or a sequence of characters?

0:51 WickedShell: bytes, although it actually takes an int as the argument

0:51 andyf: I guess the Java code calling those methods that you pasted is working as desired?

0:51 WickedShell: yeah that java code works correctly, so I believe I'm doing something wrong in clojure

0:53 andyf: What value does the .read call return?

0:54 WickedShell: the buffer is filled with bytes from the file

0:54 andyf: so it returns 1024?

0:55 WickedShell: yeah

0:56 andyf: Does the Java version get a non-null return value from mavlink_parse_char method in the first 1024 bytes?

0:57 I don't see in your paste how you initialized mavParse in Clojure code.

1:00 WickedShell: oops initilized it in the repl it was (def mavParse (Parser.))

1:02 andyf: that looks like it matches the Java init. Do you know how many times the Java version calls mavlink_parse_char before it returns a non-null value? If it is more than 1024, then the Clojure code you have shown will not get far enough.

1:02 You could change 1024 to a larger number if that is the case.

1:03 Or write a loop that keeps calling mavlink_parse_char until it returns a non-null value, or the end of file is reached.

1:03 I do not see anything wrong with the Clojure code you have tried, though.

1:04 WickedShell: There are 27 in the first 1024 bytes

1:04 I'm wondering if I'm gettting a different implicit conversion between the two

1:05 IE if I (println x) in the clojure code I get values within +/-127 while java System.ou.println(tlog.read()) gives me a range of 0-255 so I'm wodnering if thats the cause

1:06 andyf: The Java code is calling the method read that returns one int at a time, rather than a whole array of bytes.

1:06 Maybe the int values returned by the read() method return ints in the range 0..255 ?

1:08 I haven't run across that behavior with Java's FileInputStream class before, but it may be how it has worked for a long time. Seem strange to me, if that is how read() works.

1:08 If so, I bet changing the Java code to read bytes into a byte array would have the same problem your Clojure code does.

1:08 WickedShell: java returns an int or -1 on an empty file so that may be the issue ( https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#read() )

1:09 andyf: Yeah, use the read method that returns an int from your Clojure code, and I bet you get matching results in Clojure.

1:10 If you really want to use a byte buffer for some reason (e.g. maybe it gets better efficiency), you'll need to loop through only the portion of the buffer that actually gets filled by the read(byte[]) method, and convert each value -128..127 to 0..255 before passing to mavlink_parse_char

1:11 that issue is not Clojure-specific, though -- just the way the Java methods work.

1:14 WickedShell: derp, your right (and there isn't much of a gain with the buffer (and really once I got past prototyping on the file stream it turns into a network stream later)

1:14 thanks for the help

1:21 andyf: no problem

1:25 iamjarvo: http://pastie.org/private/6ekv5mneapz0xkemnxwuw this syntax should work right?

1:59 andyf: iamjarvo: looks correct

2:30 WickedShell: I think I'm missing something obvious, but how do I import multiple java classes? (the equivelent of import com.Package.* in java?) (I need 100+ java classes imported and don't want to type all the names in)

2:30 justin_smith: WickedShell: you can't

2:31 WickedShell: oh... that's... painful :/ I guess I'ma go write a generator to make me all the import statements then

2:32 justin_smith: the closest is (import '[com.foo Bar Baz ...]) but you still need to type each class out, you just don't need to repeat the package that way

2:35 WickedShell: I'm in slight shock at that still, not sure why just really surprised

2:36 justin_smith: Clojure is very opinionated about things being bound explicitly, in this case arguably to an extreme.

2:36 the plus side is you can almost always directly and clearly see where any given thing came from

2:37 WickedShell: I mean it makes sense, the problem in this case is that I'm using a library to decode a packed strucutre and the library puts each subtype of message in it's own class so I have something like 100+ classes to import

2:38 justin_smith: what about just using each one complete with package prefix instead of importing? I guess that's verbose, but it works.

2:38 or, of course, a macro

2:39 WickedShell: ie whenever referencing it use (com/package/class/method foo) everywhere?

2:39 justin_smith: the methods are not prefixed

2:39 it would be (let [instance (com.package.Class.)] (.method instance))

2:40 unless you are talking about static methods

2:40 that would be (com.package.class/method foo)

2:41 it's ugly, probably not a desirable alternative

2:41 WickedShell: its actually all just pulling public fields for the most part, with some methods

2:41 justin_smith: then (.accessor instance)

2:42 and the instance creation would be the part to either import or explicitly prefix

2:50 TEttinger: ooh ooh ooh my macro could be handy here!

2:53 WickedShell: tettinger oohh for imports/package type problems?

2:54 TEttinger: yah, I'm trying to find it

2:54 really it just lets you alias java packages

2:56 ,(defmacro import-alias [new-name imported] `(defmacro ~new-name [f# & body#] `(. ~'~imported ~f# ~@body#)))

2:56 clojurebot: #'sandbox/import-alias

2:56 TEttinger: ,(import-alias ju java.util)

2:56 clojurebot: #'sandbox/ju

2:57 TEttinger: ,(ju HashMap.)

2:57 clojurebot: #error {\n :cause "java.util"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: java.util, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6740]}\n {:type java.lang.ClassNotFoundException\n :message "java.util"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net...

2:57 TEttinger: kinda expecting that

2:58 ah, this was for changing the name of a class, not a package. still, could be altered

3:28 wow, it looks like try/catch won't actually catch class not found exceptions

3:28 can't test with clojurebot, since clojurebot doesn't allow try/catch

3:31 opqdonut: the problem is probably that the exception is in the runtime and not in your code

3:33 user=> (try (throw (ClassNotFoundException.)) (catch ClassNotFoundException e (prn :SUCCESS)))


3:36 te: !see ordnungswidrig,

3:36 !seen ordnungswidrig,

3:36 ordnungswidrig: te: poong

3:39 te: ordnungswidrig, thx for liberator, currently i'

3:44 ordnungswidrig, thx for liberator, currently i'm working on extending compojure-api (swagger) so it works better with defresource. I would like to inject a schema validation function into a liberator handler just before the body is is encoded into a representation (eg json) whats the best handler? for this purpose. For request's body I'm using the Malformed? key.

3:46 ordnungswidrig: re

3:52 te: ordnungswidrig, do you have any suggestions for the best place to inject a validation function of the response body ?

3:53 ordnungswidrig: te: what shall happen if the validation fails?

3:55 te: probably return an status code (eg. 500) or optionally log it (and then return the 'falsy' data)

4:01 ordnungswidrig: te: I think the best way would be to use a custom `as-response` function that throws an exception. handle-exception can handle that exception.

4:03 te: wait, if as-response throws and exception it's too late for handle-exception, you need to use some ring middle to handle that exception

4:04 te: thx :)

4:04 ordnungswidrig: te: or you wrap handle the handlers with a validation function that returns a 500 status using ring-response.

4:34 H4ns: i often use reduce in a fashion where based on some condition, i need to add something to the result, and if the condition or conditions don't hold, just keep the result. this often leads to unpleasant repetition of the unmodified result. is there a common idiom to deal with that?

4:35 i could wrap my reduction function with #(or (handle %1 %2) %1), but i somehow suspect that this is not the best or most idomatic way

4:36 oddcully: filter beforehand?

4:39 H4ns: not really, no - i need to process each element and accumulate if the processing yielded a non-nil result

4:40 i now have (reduce #(if-let [result (process %2)] (conj %1 result) %1) [] seq-of-elements)

4:40 but i don't like it too much

4:41 i could say (mapv (filter nil? (map process seq-of-elements))) of course

4:42 amalloy: ,(doc keep)

4:42 clojurebot: "([f] [f coll]); Returns a lazy sequence of the non-nil results of (f item). Note, this means false return values will be included. f must be free of side-effects. Returns a transducer when no collection is provided."

4:43 H4ns: amalloy: that is it, thanks!

4:43 amalloy: H4ns: honestly your reduce is literally just an implementation of filter, though. i'm unclear on why you can't just use filter

4:44 H4ns: amalloy: i'm interested in the values after processing the elements.

4:44 amalloy: right, that's a map

4:45 H4ns: keep is great, though. thanks!

6:38 entity: I want to iterate over a function that takes multiple arguments

6:38 what's the standard way to do this? Apperantly I can't use a list as a tuple

6:39 I was thinking I make the argument a tuple, but it's impossible to pattern-match on a list

6:44 TEttinger: entity: I'm not qyite sure what you mean here

6:44 iterate over a collection? using a fn that takes 2 args at a time? would be reduce

6:45 entity: ,(iterate inc 1)

6:45 clojurebot: (1 2 3 4 5 ...)

6:45 TEttinger: oh that one

6:45 entity: so what if inv takes multiple args?

6:45 inc*

6:45 TEttinger: does it take & args or does it take a fixed number over 1 args?

6:46 entity: it takes 3 args

6:46 then returns 3 again to serve as input for the next iteration

6:46 at least that was the plan

6:46 TEttinger: well returning 3 args isn't actually possible. you would return a sequence of args

6:47 let's see...

6:48 ,(defn tritri [args] (mapv (partial * 3) args))

6:48 clojurebot: #'sandbox/tritri

6:48 TEttinger: ,(take 4 (iterate tritri [1 2 3]))

6:48 clojurebot: ([1 2 3] [3 6 9] [9 18 27] [27 54 81])

6:48 TEttinger: if you have a function that takes 3 args already,

6:49 ,(defn tritri [x y z] (mapv (partial * 3) [x y z]))

6:49 clojurebot: #'sandbox/tritri

6:49 TEttinger: ,(take 4 (apply iterate (comp tritri vector) [1 2 3]))

6:49 clojurebot: #error {\n :cause "Wrong number of args (4) passed to: core/iterate"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (4) passed to: core/iterate"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 44]\n [clojure.lang.AFn applyToHelper "AFn.java" 165]\n [clojure.lang...

6:50 TEttinger: ,(take 4 (iterate (partial apply tritri) [1 2 3]))

6:50 clojurebot: ([1 2 3] [3 6 9] [9 18 27] [27 54 81])

6:50 TEttinger: there we go

6:50 entity, did any of that make sense?

6:51 TMA: ,(take 4 (iterate (comp tritri vector) [1 2 3]))

6:51 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/tritri>

6:51 TEttinger: pretty much, fns in clojure have only one return value, which can be a collection

6:51 TMA: (doc comp)

6:51 clojurebot: "([] [f] [f g] [f g & fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

6:52 TEttinger: comp isn't the right tool here, I realized

6:52 since you need to take a collection and turn it into separate args

6:52 (which is what apply does)

6:53 entity: alright, I think I got it

6:53 thanks a lot

6:53 TEttinger: cool, no prob

6:54 TMA: ,((comp) 1 2 3)

6:54 clojurebot: #error {\n :cause "Wrong number of args (3) passed to: core/identity"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (3) passed to: core/identity"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 40]\n [sandbox$eval213 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.C...

6:59 oddcully: (inc TEttinger)

6:59 lazybot: ⇒ 55

6:59 TEttinger: thanks!

7:03 TMA: ,(defn comp-- ([] identity) ([f] f) ([f & gs] (fn [& a] (f (apply (apply comp-- gs) a)))))

7:03 clojurebot: #'sandbox/comp--

7:04 TMA: ,(comp--)

7:04 clojurebot: #object[clojure.core$identity 0x55769723 "clojure.core$identity@55769723"]

7:04 TMA: ,(comp-- comp--)

7:04 clojurebot: #object[sandbox$comp__ 0x7c7bdd9 "sandbox$comp__@7c7bdd9"]

7:04 TMA: ,((comp-- inc inc) 0)

7:04 clojurebot: 2

7:04 TMA: ,((comp-- inc inc inc) 0)

7:04 clojurebot: 3

7:05 * TMA shall now remember what comp does

7:29 noncom: hello! i'd be glad if annyone can suggest a solution: https://groups.google.com/forum/#!topic/clojure/dY4AmXCDnxw

7:36 donbonifacio: how can I do a (if (empty-atom?) (swap...) (deref atom)) atomically?

7:38 hyPiRion: donbonifacio: what is the function `empty-atom?` doing? Does it take the atom as a parameter?

7:38 donbonifacio: yes, it derefs the atom to check if it has something

7:39 hyPiRion: donbonifacio: (swap! atom (fn [content] (if (empty? content) content (do-stuff-on content))))

7:40 donbonifacio: ah, nice, thanks hyPiRion

7:40 hyPiRion: np

8:16 crocket: How can I make a list reader form do nothing?

8:19 Hello?

8:20 gfredericks: crocket: hello

8:21 crocket: I'm not sure what your question means

8:21 crocket: (+ 1 2 (+ 1 2)<--ignore this)

8:22 gfredericks: ,(+ 1 2 #_ (+ 1 2))

8:22 hyPiRion: (+ 1 2 #_(+ 1 3))

8:22 clojurebot: 3

8:22 crocket: Ah yes

8:22 #_

8:22 The joy of #_

9:04 kaiyin: could anyone help with this? http://stackoverflow.com/questions/30374620/unbound-fn-error-while-function-is-declared-and-defined

9:16 noncom: kaiyin: it has nothing to do with arity. for some mysterious reason, this kind of error always comes up from that throwArity thing... idk :)

9:17 kaiyin: as for your problem - you're calling the function before it is being defined

9:18 kaiyin: as a solution - place the declaration before the call. if this is not possible due to a dependency among fns, then, as a workaround, - add (declare new-board) top form somewhere before your first call to the function

9:19 kaiyin: ok

9:19 noncom: noncom: also, as the commenters have pointed out, there is some mess with namespaces..

9:24 kaiyin: yeah, there is, I move the code a round a bit.

9:24 crocket: How do I solve http://www.4clojure.com/problem/134 ?

9:26 i-blis: crocket: contains? ?

9:28 crocket: #(and (contains? %2 %1) (= nil (%1 %2))) solves http://www.4clojure.com/problem/134

9:29 i-blis: crocket: nil? on get with non-nil default value works too

9:31 crocket: i-blis, like #(nil? (get %2 %1 :not-found))?

9:31 i-blis: crocket: for instance (i like the :not-found, more readable than false or whatever)

10:27 entity: ,(map inc [1 2 3])

10:27 clojurebot: (2 3 4)

10:27 entity: hm, why does that return a list and not a vector?

10:28 matthavener: entity: it returns a seq

10:28 if you want a vector you can use mapv

10:28 entity: ah, nice

10:28 thanks

10:28 matthavener: sure

11:12 justin_smith: entity: most clojure functions do not preserve the type of their input

11:12 entity: one trick though is (into (empty c) (map f c))

11:12 which gets the order funky for lists, but preserves type

11:14 ,(defn finc [c] (into (empty c) (map inc c)))

11:14 clojurebot: #'sandbox/finc

11:14 justin_smith: (finc #{1 2 3})

11:14 ,(finc #{1 2 3})

11:14 clojurebot: #{4 3 2}

11:14 justin_smith: ,(finc '(1 2 3))

11:14 clojurebot: (4 3 2)

11:14 justin_smith: ,(finc [1 2 3])

11:14 clojurebot: [2 3 4]

11:29 entity: justin_smith: thanks, good to know that

11:44 puredanger: justin_smith: see http://clojure.github.io/algo.generic/clojure.algo.generic.functor-api.html#clojure.algo.generic.functor/fmap for that :)

11:45 justin_smith: puredanger: I did name that silly function finc for a reason, thanks

11:45 puredanger: although really I'd just recommend using transducers now for that

11:45 ,(into [] (map inc) [1 2 3])

11:45 clojurebot: [2 3 4]

11:45 puredanger: ,(into #{} (map inc) #{1 2 3})

11:45 clojurebot: #{4 3 2}

11:46 justin_smith: ,(into () (map inc) '(1 2 3))

11:46 clojurebot: (4 3 2)

11:46 puredanger: transducers separate input source from transformation from output target and let you make those decisions separately

11:47 justin_smith: (inc puredanger)

11:47 lazybot: ⇒ 56

12:28 andyf: puredanger: No open issues for Clojure 1.7.0. Congrats! (Not to say that none will arise, but IT'S CLOSE!)

12:28 puredanger: I'm shutting down jira

12:29 :)

12:29 andyf: NO! All those hours of work.

12:29 puredanger: rc1 is in the chute

12:29 * arrdem digs for party poppers

12:30 andyf: puredanger: Are you part bulldog, by any chance? :)

12:30 (referring to the persistence bordering on stubbornness that it takes to get these things through, not your anatomy)

12:31 justin_smith: andyf: I often tell people who are interested in learning to program that stubbornness is the main required trait.

12:32 andyf: So many words with different connotations, e.g. stubborn / persistent

12:33 TEttinger: justin_smith yeah, agreed

12:33 the willingness to keep at a seemingly impossible problem until it clicks

12:34 wink: or until someone releases the bugfix

12:34 justin_smith: heh

12:34 wasamasa: TEttinger: that's how I feel all the time now that I'm learning frontend development with om

12:34 it's just so different ._.

12:34 wink: no seriously, no matter how full stack you are - at some point it's a kernel/fs/firmware issue :P

12:34 TEttinger: or even hardware

12:35 TMA: that's not stubborness, that's perseverance

12:35 TEttinger: maybe your thing works on intel but not AMD CPUs!

12:35 wink: TEttinger: yes, but then it's called replacement and not fix :P

12:35 TEttinger: not necessarily

12:35 if you're releasing code that only works on some end users' machines, it needs a fix :)

12:36 thankfully, JVM helps a lot there

12:36 puredanger: Clojure 1.7.0-RC1 is out https://groups.google.com/forum/#!msg/clojure/ccZuKTYKDPc/xpaz44UDqYwJ

12:36 TEttinger: woo puredanger!

12:36 (inc puredanger)

12:36 lazybot: ⇒ 57

12:36 TEttinger: (inc clojure)

12:36 lazybot: ⇒ 23

12:37 puredanger: now everyone go try it and tell me it's great so we can release it

12:40 TEttinger: is it on clojars or maven central yet?

12:40 puredanger: Maven central

12:41 justin_smith: TEttinger: I don't think clojure.core ever canonically ends up in clojars?

12:42 TEttinger: yah, you're right

12:44 puredanger: correct

12:50 justin_smith: TEttinger: another good one is a very firm sense of the importance of minor distinctions :)

12:50 TEttinger: pedantic mode

12:50 arrdem: -Wpendantic

12:51 were transients new in 1.6? I forget...

12:51 I don't think they were 1.4

12:51 Bronsa: 1.2 or earlier

12:52 arrdem: thanks Bronsa

12:52 Bronsa: ,(-> #'transient meta :added)

12:52 clojurebot: "1.1"

12:57 puredanger: Props to Stu H for screening tickets and releasing RC1 on his birthday :)

13:03 ionthas: Hei! Is there any way to remove the first element of a vector? I'm using (pop (vector 1 2 3)) but that it's not what I want.

13:03 Bronsa: (inc puredanger)

13:03 lazybot: ⇒ 58

13:04 Bronsa: ionthas: not efficiently, you should use a list for that

13:04 ionthas: you can get a subvector in constant time but the elemnts you're not accessing will stay in memory

13:05 ionthas: mmm... I'm trying to program a genetic algorithm using lists instead of vectors will affect the performance in any way?

13:07 TEttinger: ionthas, short answer yes

13:07 but not predictably in general

13:07 puredanger: You might want something like finger trees instead

13:07 TEttinger: there's a reason clojure has both

13:08 you may, if you don't specifically want persistent immutable behavior, find a java collection useful

13:10 ionthas: thanks! I will look at them.

13:17 TEttinger: http://b010.blogspot.com/2009/05/speed-comparison-of-1-javas-built-in.html not sure how relevant this is 6 years later

13:18 incanter includes the lib that performed best there https://github.com/incanter/incanter

13:18 also incanter should be much easier to use from clojure

13:20 iamjarvo: so i am trying to use environ and it seems like ":plugins [[lein-environ "1.0.0"]]" that is definitely needed but the instructions say "If you want to be able to draw settings from the Leiningen project map, you'll also need the following plugin:" am i doing something wrong? it's in a fresh lein app. i was getting CompilerException java.lang.Exception: namespace 'environ.core' not found, compiling:

13:21 ionthas: TEttinger: I didn't know that lib, I will look at it. thanks!

13:22 TEttinger: iamjarvo: it may be needed in profile. I do not know what environ is.

13:45 puredanger: I think you can also just hack the .lein-environ file too

13:47 You might also look at immuconf

14:13 andyf: gfredericks: Not sure if you are interested in dynalint still, but I've got a fork with some enhancements & better docs you may be interested to try out: https://github.com/jafingerhut/dynalint

14:13 You have to 'lein install' it yourself. Not released as a JAR anywhere yet.

14:42 TimMc: puredanger: There's one problem I'm seeing upgrading from 1.6 to 1.7 that could be a Clojure thing or could be a classpath thing.

14:43 Probably the latter, but I don't have a lot of time to debug it right now to be sure. :-(

14:48 gfredericks: andyf: cool, thanks -- are you trying to get that merged back to the main project?

14:50 TimMc: (clj-http.util/url-encode is yelling about not being called with the right arity even though it is definitely being called with the right one -- and calling source on it from the REPL gives the wrong line. *Probably* classpath or build tool issues...)

14:55 I wish there was a way to quickly bisect a code base to create SSCCEs.

15:02 andyf: gfredericks: Definitely. I'm just being impatient by mentioning it more widely before that happens :)

15:03 puredanger: TimMc: sounds like your env to me but let me know

15:04 TimMc: If it's clj it would have to be a classloader thing.

15:06 Bronsa: TimMc: the classloader doesn't change a var's arity :)

15:07 TimMc: AOT!

15:07 * TimMc shakes fist

15:10 TimMc: We have an AOT'd library that depends on clj-http and the main project also depends on it... but of a different version.

15:11 Bronsa: ah, that changed in 1.7 then, yeah

15:11 puredanger: what changed?

15:12 Bronsa: puredanger: 1.6 loaded AOT first, 1.7 loads clj first if clj is newer than AOT

15:13 so if TimMc has both a jit and an aot version of the same library in its classpath, it could behave differently

15:13 clojurebot: Excuse me?

15:13 puredanger: gotcha

15:13 TimMc: So... both answers are right, then. :-(

15:14 puredanger: can you exclude the version you don't want in your deps?

15:14 Bronsa: puredanger: I believe he's having the same issue core.typed had -- one of its deps is distributing an AOT version of another lib

15:15 puredanger: yeah

15:15 (did we ever fix that for core.typed? I know I looked at it but I can't remember now.)

15:15 Bronsa: puredanger: yeah I saw ambrose close the ticket days ago

15:16 or weeks -- I'm not good with time :P

15:18 https://github.com/clojure/core.typed/commit/e0f9bb33e37503f4ab51a4af61abaa2f63442b35

15:20 TimMc: Is there a generic solution to this?

15:21 puredanger: don't do that?

15:22 Bronsa: probably the transitive AOT stuff will help

15:22 puredanger: I don't know enough about your classpath to understand exactly what to suggest

15:23 TimMc: puredanger: It's a library that we AOT so Java consumers can use it, but when Clojure consumers use it, things get gross.

15:24 Bronsa: Ooh, do tell.

15:24 puredanger: Bronsa: you mean CLJ-322?

15:24 Bronsa: TimMc: well the ticket is still open and AFAIK no decision has been made so it can't really help you right now

15:24 puredanger: (also kinda worried that I didn't have to look up that #)

15:24 Bronsa: puredanger: yeah

15:25 TimMc: Aw, I thought you were implying something was on the way.

15:25 puredanger: TimMc: are the Clojure consumers using the AOT or the non-AOT?

15:25 TimMc: AOT. We only produce one artifact.

15:25 puredanger: so where does the non-AOT version come in?

15:26 Bronsa: puredanger: heh, I spend way less time than you do spelunking tickets in jira and have a number of tickets memorized too

15:27 TimMc: puredanger: It doesn't, I think there's a misunderstanding. Library A is AOT'd, app B uses library A, both use clj-http.

15:27 Bronsa: puredanger: TimMc I thought about that ticket because this problem currently arises in clojure since there's no way to AOT library code and not deps code.

15:27 puredanger: does A happen to also include an AOT'ed version of clj-http?

15:27 TimMc: puredanger: Yes, exactly.

15:27 Bronsa: TimMc: just exclude clj-http so it doesn't get pulled in. you'll use the AOT version included in A

15:27 puredanger: ah

15:28 TimMc: Bronsa: Each consumer of lib A has to do this, yes? Transitively?

15:28 puredanger: well I think the problem is that A includes AOT'ed deps

15:28 Bronsa: TimMc: dunno

15:28 puredanger: A's jar should include... A

15:29 TimMc: That's difficult with current tooling. :-(

15:29 Bronsa: puredanger: yeah but if we want to be honest the problem is that clojure has no way to avoid AOT compiling deps

15:29 puredanger: I hear ya

15:30 TimMc: leiningen I presume?

15:30 TimMc: yeah

15:31 puredanger: so this is CLJ-322 as Bronsa said

15:32 TimMc: One approach would be to construct a compilation boundary around the core of lib A such that only the very outer interface is AOT'd and the rest is loaded dynamically.

15:32 Easy to do with an app (a la lein-otf), harder to do with a lib.

15:32 Bronsa: TimMc: hacky solution is to JIT load all deps before AOT compilation starts

15:33 sorbo_: I'm trying to accomplish what this SO user is looking for: http://stackoverflow.com/questions/16320739/merge-with-merge-can-this-be-simplified

15:33 Bronsa: TimMc: super hacky solution is to do that in user.clj

15:33 puredanger: bleh

15:33 Bronsa: don't judge me

15:33 sorbo_: but his/her `(val ...)` solution doesn't seem to work (ClassCastException user$eval803$fn__804 cannot be cast to clojure.lang.IPersistentCollection)

15:33 and I can't use the accepted solution because my keys are not contiguous

15:33 TimMc: Bronsa: "JIT load all deps before AOT compilation starts", how would this work?

15:34 sorbo_: anyone successfully done a (merge-with merge) to selectively merge a vector of maps?

15:34 puredanger: Bronsa: I'm not. not your fault... :)

15:36 I have done a few builds where we post-processed to filter just things we wanted in the AOT jar

15:36 definitely works, also definitely annoying

15:37 TimMc: sorbo_: Sort by id first?

15:37 sorbo_: TimMc: then they'll increase monotonically, but they won't be contiguous (there'll be gaps)

15:37 will that still work with partition-by?

15:38 Bronsa: TimMc: disclaimer: it's terribly hacky and horrible, but if you add a src/user.clj filled with "(require 'my.dep)", those deps will be JIT loaded by leiningen, and won't be loaded (thus compiled) when compiling the lib

15:38 TimMc: sorbo_: I don't know what you mean by "gaps". The SO question could have :id values 1 and 1000, it doesn't matter.

15:38 Bronsa: TimMc: still something that needs to be done in lib A though, nothing you can do just as a consumer

15:38 TimMc: Bronsa: Fascinating. /me sidles away

15:39 Bronsa: TimMc: OT but was your last `c` always lowcase?

15:39 TimMc: yeah

15:40 short for Tim McCormack

15:40 Bronsa: stupid brain is playing tricks on my memory then

15:42 creese: What's the best way to build when you have private dependencies?

15:42 xemdetia: TimMC is just his DJ name

15:42 creese: I've been using checkouts to develop.

15:43 puredanger: use a private repository?

15:44 wink: (inc xemdetia)

15:44 lazybot: ⇒ 5

15:44 TimMc: xemdetia: :-)

15:47 creese: puredanger: maven repository?

15:47 TimMc: ~repeatability

15:47 clojurebot: repeatability is crucial for builds, see https://github.com/technomancy/leiningen/wiki/Repeatability

15:47 TimMc: creese: ^ I think this has some options.

15:47 arohner: creese: yes, you'll want a private maven repo

15:48 I like https://github.com/technomancy/s3-wagon-private, but that works for everything except lein plugins

15:48 TimMc: The private S3 bucket is another solution.

15:48 arohner: Ah, interesting!

15:48 arohner: TimMc: something about when lein loads plugins vs. resolves deps

15:48 puredanger: I've found s3-wagon-private to work pretty well

15:48 I've also run a company nexus etc

15:49 that has other potential benefits - like caching the internet, allowing you to set policies, potentially serve to public, etc

15:49 TimMc: arohner: Hmm, makes sense -- a plugin that determines how plugins are loaded would be tricky.

15:49 * TimMc uploads s3-wagon-private to an S3 bucket

15:50 arohner: puredanger: I wrote a plugin to cache the internet in S3 :-)

15:50 now, what was it called...

15:51 TFW when you released a plugin, used it in production, and can't remember it's name

15:52 creese: puredanger: is it possible to build locally?

15:52 arohner: aha, https://github.com/circleci/lein-deploy-deps

15:52 I forked it, not original

15:53 TimMc: creese: You *can* deploy private stuff to a local filesystem repo, but it will eventually cause you sadness.

15:54 puredanger: well if you're in a team, that sadness will start right away :)

15:54 creese: ok

15:54 I'll try the wagon one

15:54 justin_smith: andyf: is there a way to make eastwood warn me if I require a namespace but don't use it?

15:55 TimMc: puredanger: True!

15:55 Bronsa: justin_smith: enable the :unused-namespaces linter

15:55 justin_smith: Bronsa: cool, thanks

15:56 (inc Bronsa)

15:56 lazybot: ⇒ 111

15:59 kaiyin: could anyone help with this? http://stackoverflow.com/questions/30383222/side-effects-not-realized-without-deref

16:13 zerokarmaleft: does instaparse have a pretty printer for failures that returns a formatted string instead of actually printing to stdout?

16:15 I suppose I could just use with-out-str

16:21 fourq: I see "xs" used often as a param in clojure examples. What the significance?

16:21 or rather as an arg to a function signature

16:22 (fn [xs] (vec (remove #(= contact %) xs)))

16:22 infinity777: Disco Melee is hiring Clojure developers to accelerate the development of our platform. Come join the team that is attempting to redefine social streaming! https://docs.google.com/document/d/1GvnrSCUbYgbY9XdFs_DUx-0QZG2bIYT8Mbr0zdpTeew/edit?usp=sharing

16:29 amalloy: fourq: plural of x

16:30 fourq: hehe really?

16:30 andyf: justin_smith: Try enabling the linter called :unused-namespaces (IIRC), which is disabled by default because it can be too noisy

16:30 Sample command line: lein eastwood '{:add-linters [:unused-namespaces]}'

16:31 dnolen: fourq: FP convention I believe arising either from Philip Wadler or David Turner

16:31 fourq: interesting. thanks amalloy, dnolen

16:31 andyf: justin_smith: Yeah, checked the docs and that should be the one. A little bit more about it here: https://github.com/jonase/eastwood#unused-namespaces

16:32 justin_smith: andyf: yeah, I actually like that linter a lot because it helps make refactors a lot cleaner

16:32 andyf: And now I'm caught up to Bronsa answering the question :-)

16:32 justin_smith: heh

16:32 you actually showed the syntax (thought I did end up looking it up myself already)

16:40 andyf: justin_smith: You can have an :eastwood key in your project.clj, or user-wide $HOME/.lein/profiles.clj, with that value, if you want it always on.

16:42 justin_smith: andyf: awesome, thanks

16:48 creese: for s3-wagon-private, where do I put pom.xml?

16:50 justin_smith: creese: "lein deploy private" should do the part where it makes a pom for you

16:51 or whatever you named the repo, if you didn't name it private like I did

16:53 creese: I'm getting an error. S3ServiceException: 404 Not Found NoSuchKey The specified key does not exist

16:53 justin_smith: creese: it does that for me on my first upload with a new project

16:53 next upload, all is well

16:53 TimMc: creese: Is that the expected error mentioned in the docs?

16:53 justin_smith: in general, s3-wagon-private throws exceptions in a lot of weird circumstances where you would not expect it

16:54 creese: weird, it's working now

16:54 justin_smith: eg. getting a stack trace because you checked if the repo contained an artifact that wasn't there

16:54 creese: like I said, it works on the second try, and throws stack traces like they grow on trees

17:29 fourq: If I want to inspect a symbol (print it to console) how should I go about it? (fn [e] (print e)) just prints that it's an Object.

17:29 should I read-string it to see it's pre-eval'd form?

17:30 in js, I would typically JSON.stringify(something)

17:30 TimMc: fourq: A symbol should print nicely. Maybe you don't have a symbol.

17:30 ,(prn 'foo)

17:30 clojurebot: foo\n

17:30 justin_smith: fourq: also, (fn [e] (print e)) is just an arity limited print

17:31 fourq: yeah, just as an ex

17:32 TimMc: fourq: Can you gist or refheap an example that shows your problem?

17:33 fourq: https://gist.github.com/fourq/7247640ac9e58cb89dcd#file-core-cljs-L16

17:33 TimMc

17:34 I'd like see what the params actually are when they are passed in

17:34 the doc's leave a bit to be desired

17:34 (Om docs)

17:35 amalloy: i don't think you care about this. it's just gonna be a function

17:35 you might care about delete

17:35 fourq: I just want to know the proper function to call in order to inspect, "this" was just my first attempt

17:35 but I am curious about it too

17:36 TimMc: fourq: Oh, you didn't mention this was CLJS. That explains a lot.

17:36 fourq: TimMc I wasn't sure it mattered considering I'd like to inspect a symbol or key

17:37 amalloy: fourq: you don't want to inspect a symbol

17:37 fourq: no? I want to eval it?

17:37 amalloy: you want to inspect a value, which you coincidentally have bound to a symbol

17:37 TimMc: fourq: You're trying to inspect a value that is *bound* to a symbol.

17:37 amalloy-sniped!

17:38 and this time I used fewer characters!

17:38 fourq: ok, so I want to inspect the value of the symbol assoc to the current ns right?

17:38 amalloy: you had to press shift more than i did. we'll say that was the problem

17:38 fourq: just to see if I got this right

17:38 you both win

17:38 TimMc: amalloy: Let's go with that.

17:39 fourq: clojure isn't coming very easy to me. I've been oop forever it seems, and between fp and the syntax, i'm just barely hanging on atm

17:39 TimMc: fourq: Just as in JS, not every value you can get your hands on is particularly amenable to printing.

17:40 fourq: even if it told me it was a func, I could (souce some-func) right?

17:40 TimMc: source is a hack

17:40 fourq: or not in cljs during runtime?

17:41 TimMc: source gets the metadata of the var, finds out the file it was defined in, then goes out to the filesystem and looks in the file and goes to the appropriate line and reads the first thing it sees.

17:41 fourq: hmm

17:41 TimMc: It's not really showing you the source of the thing as it is in memory.

17:41 amalloy: TimMc: is that true even in cljs? js actually keeps source around

17:41 fourq: ok, well how do you suggest that I inspect param values? I just want to know what I'm dealing with

17:41 amalloy: and doesn't have vars anyway

17:42 TimMc: amalloy: Man, I don't know anything about cljs.

17:42 dnolen: fourq: ClojureScript has good debugging support, use it :)

17:42 you can set breakpoints and inspect the stack frame

17:42 amalloy: fourq: (prn x)

17:42 fourq: yes, that's what I need. debugging tools

17:42 prn? diff than print, println?

17:42 dnolen: fourq: just open Chrome Dev Tools, ClojureScript enables debugging support by default

17:42 fourq: oh right, sourcemaps!

17:42 shesh

17:43 thanks, I'm like Kelly Bundy sometimes

17:43 dnolen: if you need to print something in a strackframe, cljs.core.prn(whatever) should do what you want

17:43 justin_smith: fourq: prn is different from print, it tries to print in a way that can be read back again

17:43 fourq: too much of one thing and old stuff spills out

17:43 lvh: I love that that's actually better than the situation in regular clojure

17:43 clojurebot: Huh?

17:43 justin_smith: fourq: so for example you can distinguish symbols from strings

17:43 lvh: where you can get debugging but only if you use these 2 ides

17:43 fourq: thanks everyone.

17:44 super helpful chan

18:18 mischov: Is pipeline how one would go about taking a core.async chan and returning a core.async chan that has a function applied to the contents of the original chan?

18:21 Or would you just pipe from a channel into a channel with a transformer?

18:23 chomwitt: trying to run a very simple jetty server with a simple handler leiningen will retrive 40-50 .pom packages!! 1) where do the get installed? 2) what if i change the version or a package in the dependency line in project file will that result in more retreiving ??

18:23 lazybot: chomwitt: What are you, crazy? Of course not!

18:24 chomwitt: 1) where do they get installed?

18:24 amalloy: chomwitt: (1) ~/.m2 (2) yes

18:25 chomwitt: amalloy: wow! so that makes thinks simpler in a way.. but seems more reduntant and complex in another aspect .(i mean having many version of the same library installed) in your program's dir

18:26 TimMc: chomwitt: 2) Yes, but fewer, since only a few of the dependencies are likely to change.

18:27 chomwitt: What language are you coming from?

18:27 chomwitt: c, javascript, php

18:27 and cpp

18:27 mainly webdev

18:28 clojure slowly is getting under my skin :-)

18:28 * TimMc realizes he doesn't actually know how dependency management works in C-land

18:29 justin_smith: TimMc: glib answer is "it doesn't"

18:29 chomwitt: amalloy: i found the .m2 dir. thanks!

18:29 TimMc: s/ in C-land// :-P

18:30 chomwitt: A tip: Never blow that away unless you want to re-download the internet. (But sometimes it is helpful to move it temporarily in case you suspect the repository has gotten into a bad state.)

18:30 sdegutis: Is it safe to nest -> macros?

18:30 (-> foo (-> bar)) ?

18:31 Or will that give unexpected results?

18:31 justin_smith: sdegutis: yeah, ->> inside -> is very handy

18:31 sdegutis: Great. Thanks.

18:31 TimMc: sdegutis: Ever since 1.6.0 or so, they behave properly.

18:31 sdegutis: Dang, I'm on 1.5.1

18:31 TimMc: Depends what you mean by "expected" though.

18:31 sdegutis: http://dev.clojure.org/jira/browse/CLJ-1121

18:32 amalloy: TimMc: it's always behaved fine for ->, i thought. it's nesting ->> that was a little weird

18:32 although why would you. (-> foo f (-> g h)) is always the same as (-> foo f g h)

18:32 sdegutis: True.

18:33 TimMc: sdegutis: This will run an infinite loop in 1.5.1: (macroexpand '(->> a b (->> c d)))

18:35 sdegutis: Ah.

18:35 TimMc: They used to be implemented recursively.

18:37 sdegutis: I may not even be able to do what I wanted.

18:37 I've been using the approach of taking in the same state input as the first argument as I spit out, in all my functions, so that I can chain them with ->

18:37 For example, (-> (create-cart) (add-item-to-cart "item1") (remove-item-from-cart "item2

18:37 * chomwitt thank TimMc for the tip

18:39 amalloy: sdegutis: so far so good

18:39 sdegutis: "))

18:39 But I want to add functions within.

18:40 So, (-> (create-cart) (-> (add-item-to-cart "item1") (set-item-description "foo")) (remove-item-from-cart "item2"))

18:40 amalloy: sdegutis: i mean, you can do that, but you're just using -> as a grouping construct then. it's the same as if you just lifted all the stuff inside it up into the main ->

18:41 sdegutis: Right. My API design doesn't allow for returning a sub-item in some contexts and the item itself in others.

18:42 So add-item-to-cart always returns a cart, and set-item-description must take a cart, not an item.

18:42 This is a problem in my design, and makes -> not be compatible.

18:42 amalloy: i think you mean (-> (create-cart) (add-item-to-cart (-> "item1" (set-item-description "foo"))), then

18:43 sdegutis: I suppose I could do it with (-> (create-item "item") (set-item-desc "foo"))

18:43 amalloy: here you're threading two totally distinct things, and they both make sense to thread, but they don't interact at all

18:43 sdegutis: But then that would build up a description rather than using the real state, since it has not access to the state param returned from create-cart.

18:47 The problem with the design of building up a description, is that I can't separate the APIs of creating and updating an object.

18:48 amalloy: sdegutis: did you look at my suggestion? is there some reason this is impossible to do? why does creating an item need to know about the cart it's going to be added to?

18:48 sdegutis: So if create-item and set-item-desc just build up a description of what to do, and create-item does the real work, then update-item needs also to be able to do the real work, and needs a separate way of getting a hold on an item, whereas create-item already has a reference to the item (it just created it).

18:48 amalloy: yes, I'm responding to your suggestion.

18:51 amalloy: creating an item only makes sense in the context of the cart it's being added to, since an item cannot be created separately from a cart or without a cart

18:52 amalloy: thus the creation function must take a cart immediately, to avoid having an inconsistent database state

18:52 amalloy: sdegutis: that doesn't sound like much of a model of the real world

18:52 i'm pretty sure boxes of cereal exist on the shelf even before i put them into my cart

18:52 sdegutis: amalloy: er sorry, I may be using a bad analogy, I don't really have a cart and an item in my real model, I just picked two model concepts off the top of my head for this

18:52 amalloy: I didn't realize how silly my analogy was until you said that :)

18:53 amalloy: sdegutis: i don't think you should use an analogy. i think you should describe a thing you are actually trying to do, because people have to respond to the stuff you say, rather than the stuff you are thinking

19:05 url-: aloha

19:14 travisrodman: is anyone using clojail and running into OOM issues with the JVM?

19:15 I have been using it to sequester calls, and about 1.5 days into excution, it is OOM-ing, due to references to the sandbox being retained by the DynamicClassLoader

19:15 has anyone worked around this?

19:16 amalloy: travisrodman: lazybot uses clojail, and his uptime is a bit over 2 months at the moment

19:16 travisrodman: but is lazybot using only one jail, or is it generating a new one for each request?

19:17 thanks for responding to me on this BTW

19:17 we are generating a new jail for each inbound request

19:18 amalloy: i can see how that might be a problem. why do you have to do that?

19:18 travisrodman: it is those reference that are being retained i.e., sandbox123423... eventually they are hard-referenced and overrun memory.

19:19 we are eval-ing tools written with the taxi dsl in individual containers since each caller could be defining their own logic, so we don't want namespace redefinitions and clashes

19:19 hence, we spawn a new jail per request.

19:20 normally, if this were java, we would sequester them under a class loader and dump the loader at the end of the execution, to free the memory, but the references in the clojure code are all retained by the DynamicLoader

19:21 amalloy: i'm afraid i don't know enough about the problems with classloader GC to help you, really. the usual cause of this is a thread-local variable, right? so that a thread holds a reference to an object, which holds a reference to the classloader?

19:21 travisrodman: basically yes, and the classloader in this case is the root loader in Clojure

19:22 so the only way to dump it is to restart, or to create a classloader above the Dynamic laoder, containering the system, so the parent to the DynamicLoader can be dumped

19:22 but this is clojure turtles all the way down.

19:22 in this system...

19:24 amalloy: is that assessment correct, I am not missing something that you are aware of?

19:24 amalloy: travisrodman: i'm not sure. i think there is some way to clean up the classloaders. you might look into what clojure.repl or clojure.main is doing, since it makes a new dynamic classloader for every eval request

19:25 and repls don't seem to have this problem

19:26 also, i don't know if it is at all helpful to you, but the threads created by clojail are un the threadgroup "sandbox"; if getting a reference to those threads would help you, you could try that

19:27 travisrodman: i think they are just making new DCLs, hence the fn__234123 naming, and the map constructions in the classes... that way a new function can be def'd without dumping the old class definition. this is why deftypes force a restart, since they are generating a non-generic class

19:27 yeah.. thanks, I will check avenues related to that... I appreciate it.

19:28 lazybot help

19:28 ,lazybot help

19:28 clojurebot: #error {\n :cause "Unable to resolve symbol: lazybot in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: lazybot in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: lazybot i...

19:28 travisrodman: $lazybot help

19:28 amalloy: travisrodman: hiredman probably knows more about classloaders than i do. he's responsible for clojurebot, which doesn't use clojail, but probably has similar issues

19:28 travisrodman: ahh, I thought this channel was using lazybot...

19:28 or, is it?

19:29 Raynes: There are two bots in this channel.

19:29 Both of them.

19:29 travisrodman: ,(defn test-fxn [a] (println a))

19:29 clojurebot: #'sandbox/test-fxn

19:29 travisrodman: ,(test-fxn "print me")

19:29 clojurebot: print me\n

19:30 travisrodman: ,(defn test-fxn [a] (println (str a "some other data")))

19:30 clojurebot: #'sandbox/test-fxn

19:30 travisrodman: ,(test-fxn "print me")

19:30 clojurebot: print mesome other data\n

19:30 travisrodman: hmm... it looks to use the same namespace for every request

19:30 Raynes: Well, yes.

19:30 That's half of the purpose of clojail.

19:30 To make that a thing that can safely be done.

19:30 It does a pretty solid job of that when it does a pretty solid job of that.

19:31 travisrodman: but that means everyone is using the same namespace

19:31 so any defs happening in that space will clash with everyone else

19:31 which is fine... as long as it is an acceptable situation

19:31 url-: why not just wrap an Actor around the sandbox?

19:33 travisrodman: url-: i will look into that

19:34 url-: if you think of it as a service instead of a monolithic object that may help frame out a solution

19:35 travisrodman: url-: well, it is a service, spread over 25 machines, but each of them can be running over 60 tools each...

19:36 url-: originally, the design was to allow people to design their own tools, so we didn't want them clashing with each other, hence the sandboxing

19:36 url-: but we may forego that to avoid the memory problems

19:38 url-: thanks for the actor tip, i will look into seeing if it will work with the current model. thanks!

19:42 amalloy: i may re-think this entire approach with using binding to abstract the tool... that way a single sandbox could be used, but the memory will be assocaiated with the thread, and not the namespace so it can be dumped...

19:42 thanks all for the feedback, and Raynes, thanks for the lib, it really is useful... sorry about appering to knock on it... it is a good piece of work.

19:43 Raynes: I read approximately two of your prior messages, so I appreciate your honesty.

19:43 amalloy: travisrodman: if the need for sandboxing is just for sequestration, you can avoid putting stuff into namespaces, but instead use your own named maps, and give those around to whatever this "tool" is

19:43 then you wouldn't need multiple sandboxes, as you say

19:44 Raynes: Clojail is way more of an experiment in how far you can go with Clojure's metaprogramming facilities to implement an embedded sandbox.

19:44 If I were rewriting tryclojure today, I'd be unlikely to use it.

19:44 Same goes for lazybot.

19:44 travisrodman: amalloy: right... I am thinking that approach could be a viable solution... thanks again for the feedback

19:44 Raynes: intersting... what would you do instead?

19:45 * amalloy is curious too

19:45 Raynes: Ephemeral machines.

19:45 Better yet, docker

19:45 Sometimes of that sort.

19:45 And lots of money to afford the memory consumption of a JVM process.

19:46 Tryclj would be horrifying to scale, but it'd actually work properly.

19:47 amalloy: even ephemeral JVMs in one machine would work okay

19:47 Raynes: Not if you don't use the JVM sandbox.

19:47 amalloy: sure

19:47 Raynes: Or something like docker

19:47 Or selinux

20:11 travisrodman: thanks for describing your approach... sorry, had to step away for a moment.

20:12 Raynes: --^

20:50 WickedShell: I have a seesaw gui using swinglayout, when I update the items in my mig panel any items that had been in it before I swapped the other items disappear, but if I fully rebuild the panel works correctly, any idea why this is happening?

21:06 mcohen01: anything obvious to look for when lein uberjar never finishes?

21:06 WickedShell: I apologize, I had it right before, spelling errors are the root of all evil (and you know, running the same misspelled command again)

21:06 mcohen01: i've got a main method that does nothing and it still hangs

21:06 with no imports either

21:13 justin_smith: mcohen01: (shutdown-agents)

21:13 mcohen01: clojure starts an agent pool, the vm doesn't want to quite while that pool is running

21:14 mcohen01: oh, uberjar - you are probably using def to create a server

21:14 amalloy: justin_smith: if it's lein uberjar that never finishes, shutdown-agents is not the answer

21:14 justin_smith: or spawn a thread that does something

21:14 amalloy: right

21:14 mcohen01: if you use jstack to get a dump for all your running stacks (it's a command line program, run outside the vm) one of those stack traces will have your offending code in it

21:35 travisrodman: amalloy: are you still there?

21:44 mcohen01: justin_smith: thanks much for the recommendation re jstack. worked like a charm. i was starting a netty hashwheeltimer and didn

21:44 t't realize it

21:45 amalloy: travisrodman: what's up?

21:49 travisrodman: amalloy: just wanted to give you a working solution to the earlier question, if you are interested...

21:49 amalloy: i set up a pool for the sandboxes, so when a session closses, it is returned to the pool.

21:50 it is still possible to crash the system, but essentially, you would have to have all the sessions (millions) persist in parallel for that to happen

21:50 not a likely scenario. so in the event you need to have individual jails, it appears to be a viable solution

21:50 fyi

22:27 wha123: I am getting a ClassNotFoundException when trying to pass a custom record type to a Java library

22:28 gfredericks: wha123: probably some code & stack trace would help

22:59 wha123: the issue seems to be that the Java library is trying to load a class using Class.forName(string_name_of_class), and it can't find the class for my record

23:00 gfredericks: huh.

23:00 I wonder if AOT could fix that.

23:00 justin_smith: wha123: are you providing the full munged and package qualified class name?

23:00 gfredericks: justin_smith: I imagined an object was being passed in and something reflective was happening. Which made me guess classloaders were to blame

23:01 wha123: Yeah, I originally pass in an object, and it uses reflection to get the class name and writes it out to a file (it is part of a serialization framework)

23:02 but then when trying to deserialize, it can't find the class

23:02 justin_smith: during the same vm session, or a later one?

23:02 wha123: all in the same repl session currently

23:05 gfredericks: I blame ye olde classloaders

23:05 wha123: yeah, Class/forName works in the repl as well -_-

23:05 gfredericks: make sure the defrecord is in one of your source files, add :aot :all to your project.clj, quit the repl, run `lein do clean, compile` and then `lein repl` and try it again

23:05 wha123: it must be using its own

23:06 gfredericks: I don't actually know how classloaders work so who knows if this will do it or not

Logging service provided by n01se.net