#clojure log - Dec 04 2014

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

1:03 rritoch: Is it possible to copy a var from one namespace to another in such a way that any bindings on that var will automatically appear on both namespaces?

1:05 For example, creating a dynamic var in a library, and also linking that var to the clojure.core namespace to make it available globally.

2:29 dysfun: rritoch: have you tried interning the var?

2:30 ,(def :^dynamic t1 "foo")

2:30 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :>

2:30 dysfun: ,(def ^:dynamic t1 "foo")

2:30 clojurebot: #'sandbox/t1

2:30 * dysfun plays at a repl for a mo

2:31 akkad: irc support for eval is nice :P

2:32 dysfun: yeah, but i'm going to make a few mistakes figuring out how it's going to work, so i've moved to another terminal tab :)

2:32 rritoch: dysfun: No I haven't tried, but it does seem like a good way of doing it. Is there an upgrade-safe way of interning vars?

2:33 dysfun: 'upgrade-safe'?

2:33 rritoch: dysfun: Upgrade safe means that it doesn't rely on undocumented features of clojure that are subject to change in future versions.

2:33 dysfun: In other words it "should" work in all future versions of clojure

2:34 dysfun: well i don't think the semantics of intern are going to change any time soon, having read the clojure source code

2:34 rritoch: dysfun: If not, I'm OK with that, but keeping code upgrade safe when possible is ideal.

2:34 dysfun: well if you want to be sure, i'd recommend not doing that

2:35 if you want values to be visible elsewhere, either put them there to start with (intern is fine for that) and then bind those instead

2:35 or use an atom or something

2:35 but e.g. noir doesn't try to solve this, you just import the dynamic var from their namespace and use it in all the modules you need to

2:36 http://www.webnoir.org/autodoc/1.2.1/noir.request-api.html

2:36 cfleming: Hi everyone. A colleague of mine has a very strange problem with records.

2:36 Refheap: https://www.refheap.com/94392

2:37 What is happening is that a different class is returned depending on whether he uses the class constructor (TestRecord.) or the constructor function (->TestRecord)

2:38 The classloader is also different - the constructor function version uses a dynamic classloader and the class constructor version uses the system classloader.

2:39 dysfun: that's some odd but easily explained behaviour. what i'm not seeing is why this matters

2:39 cfleming: dysfun: The record problem, you mean?

2:39 dysfun: clojure does a lot of clever things involving rather a lot of classloaders

2:40 yes, what is the actual problem?

2:40 is it you are having difficulty testing the identity?

2:40 cfleming: If you look at the refheap, only one of the records correctly dispatches the multimethod

2:40 dysfun: ooh i get it now

2:41 cfleming: Plus equality will fail, polymorphism won't work...

2:41 I don't understand where the dynamic classloader is coming from.

2:41 dysfun: okay, perhaps i can explain that to you

2:41 one really useful thing in clojure is being able to redefine things

2:42 unfortunately owing to jvm limitations, you just can't

2:42 cfleming: Yup

2:42 dysfun: but you can take a classloader from before something was defined and use that, whereupon it doesn't exist

2:42 clojure allocates a new classloader to every top level expression

2:43 cfleming: But all those classloaders should delegate to the system classloader, right?

2:44 dysfun: should they? then you wouldn't be able to load something twice

2:44 i mean the loading mechanism is certainly the same, but the need to be able to redefine stuff is great

2:44 cfleming: They have to, otherwise you would end up loading all the clojure classes in every classloader.

2:44 Symbol, Keyword, PersistentHashMap...

2:45 dysfun: classloaders work as a tree

2:45 cfleming: Right.

2:45 dysfun: so a classloader is almost like a new interpreter. as far as namespacing goes, it pretty much is

2:45 and obviously you could limit it to loading from a specific jar etc.

2:46 cfleming: Only if everything is loaded into that classloader

2:46 dysfun: ah, that's where clojure does magic

2:46 cfleming: Which it can't be - those base level classes aren't reloaded on every expression.

2:46 dysfun: don't ask how it works, i'm not 100% on it but current understanding says it mostly works because clojure does value semantics on everything

2:47 cfleming: In this case I think I need to actually know how it works to figure out what's going on.

2:47 dysfun: in that case, you'll need to find someone with more understanding of the guts of clojure than me, or to read the source

2:47 if you do figure it out, i'd love to know the answer

2:48 cfleming: Ok, I'll research around a bit.

2:48 dysfun: but hopefully you understand a bit more now

2:49 * dysfun feels a clojure blog post coming on

2:49 cfleming: Here's hoping - I can't find any information about this

2:50 rritoch: dysfun: What if he binds the app classloader to Compiler/LOADER ? It seems like ->Method is using RT, so if it does than binding Compiler/LOADER should prevent clojure from creating a new classloader, right?

2:50 cfleming: Joy of Clojure doesn't even contain the word classloader. Programming Clojure only mentions it once.

2:51 Here's what I don't understand:

2:51 I'm assuming that there must be a parent classloader that all these per-expression classloaders delegate to.

2:52 dysfun: rritoch: that seems like a reasonable workaround, i haven't tried it

2:52 cfleming: do you understand how the classloader system works?

2:52 cfleming: In this case, it looks like the system classloader, because that's where the TestRecord class ends up being defined.

2:52 dysfun: Yes I do.

2:52 At least, I do in Java - I'm not sure how Clojure uses classloaders.

2:52 dysfun: well, i'm talking about the java bit

2:52 cfleming: Yes.

2:53 dysfun: about how delegation works, in particular

2:53 cfleming: Yep.

2:54 So, in this case the TestRecord class ends up being defined in the system classloader, I'm assuming because that way it will be available to all future expressions in this file, even if they're using fresh classloaders.

2:54 dysfun: okay, try running that at the repl

2:54 cfleming: What I don't know is why the class later gets redefined in a different classloader, presumably a per-expression one.

2:55 dysfun: i get both as DynamicClassLoader

2:55 and both as TestRecord

2:55 are you AOTing, perchance?

2:56 cfleming: Yes, this is with lein compile

2:56 dysfun: right, turn off AOT on that namespace and try again

2:56 cfleming: I'm sure that will work.

2:56 What I'd like to understand is why the other doesn't.

2:57 dysfun: well, see if it works first :)

3:01 cfleming: Yup, definitely works :-)

3:01 dysfun: well that's a start. now let's figure out why :)

3:01 cfleming: Interestingly, I see the same dynamic loader both times.

3:01 dysfun: "top level expression"

3:02 oh, i read those as being nested, they are separate

3:03 i don't know. it's not really my area (although i have some horrible classloader/securitymanager stuff on the horizon which will require me to learn more...)

3:04 cfleming: Right, they're separate.

3:06 So, I can get the dynamic classloader of that class. I then navigated through its parent hierarchy - I have to go up 6 levels (!!!) of dynamic loaders before I get to the AppClassLoader

3:06 dysfun: classloaders are cheap

3:09 cfleming: Ok, so DCL uses the standard delegation model.

3:10 If that's the case, then in the AOT example, if the class is defined in the system classloader, how does it ever get loaded into a DCL?

3:15 dysfun: is it defined in the system classloader though?

3:15 i suspect it's defined further down the chain

3:15 because i know you can in fact even load multiple clojure versions on the same jvm in parallel

3:15 (see classlojure)

3:17 rritoch: dysfun: I tried the binding trick, it doesn't work, if I require from repl both use the application class loader, it is only during lein compile that this dynamic classloader gets generated.

3:18 cfleming: Yes, it is - see this line: ; .. #classloader.core.TestRecord{:foo nil} sun.misc.Launcher$AppClassLoader@288d539f 1971347490

3:19 dysfun: no, that just means it's being run on an AppClassLoader instance

3:19 which isn't the same thing as the root classloader

3:20 cfleming: Right, I shouldn't have said the system class loader - what I mean is a standard classloader outside the DCL chain.

3:21 dysfun: is the whole thing done through subclassing? isn't it possible there's something that drives a classloader?

3:21 cfleming: I suspect it's being loaded there due to AOT, which is fine. What I don't know is why there's ever another instance of the record class defined

3:22 dysfun: oh, i may be able to explain that

3:22 cfleming: In fact, there's a bug which suggests that it's not - http://dev.clojure.org/jira/browse/CLJ-371

3:22 dysfun: AOT generates a stub class, not the full thing

3:22 cfleming: Well, it is, but the AOT'ed one will always be found because it's always in a parent CL

3:22 You're talking about gen-class though, right? Not classes generated from records?

3:24 dysfun: i'm not sure any more. i tend to always use the map->record form

3:25 that and ->record are certainly workarounds

3:27 cfleming: Except it's not, really - the multimethod dispatch doesn't work.

3:27 instance? won't either.

3:27 dysfun: your example shows it working?

3:28 sorry if i'm being thick, it's still early here and i haven't finished my coffee, but it looks like it's working in the ->record case

3:29 anyway, in general, AOT makes bad things happen which is why you should avoid it where possible

3:31 cfleming: Sadly that's not always an option.

3:31 dysfun: yeah, i know :(

3:31 cfleming: Here's what seems to be happening

3:32 I think that the AOT compiles the class, and then it presumably gets loaded into the AppClassLoader when the ns is loaded.

3:33 However the Compiler, whenever it sees a "new" expression uses LOADER.deref(), which is always a DynamicClassLoader

3:34 Actually, wait - I think this is the stub you were talking about, my apologies, it looks like it does this in more cases than just gen-class

3:38 echo-area: I see that the version number of core.async contains "alpha". Is it now suitable to use it for production?

3:50 dysfun: cfleming: heh

3:50 echo-area: that depends entirely upon your attitude to risk. in the sense of APIs may change, bugs may be fixed later

3:51 * dysfun would be cautious

3:53 echo-area: dysfun: I have no experience using it yet, and so cannot be sure what kind of issues I would have. And my application is very serious. I think I might not put it into production at the moment.

3:53 dysfun: Thanks

3:54 dysfun: echo-area: multithreaded programming in clojure is practically a joy, i'm reluctant to leave behind those niceties to write core.async

3:54 szymanowski: Hi, i'm struggling a bit here, i've got A: a lazy-seq of indexes, and B: a coll (possibly lazy-seq), i'm trying to write a fn that select all the indexes present in A from B, could anyone give me an hint for doing that properly?

3:55 echo-area: dysfun: Sure, and I am using agents by now.

3:55 dysfun: agents rock :)

3:56 rritoch: I'm not sure if this helps or not, but I found the source of the dynamic class loader. It seems TestRecord is interned into the namespace as the symbol TestRecord, but when using dot notation (TestRecord.) it doesn't use the interned class which seems to be a bug

3:57 When I added (println (pr-str (.getClassLoader TestRecord))) to the source file, it outputs the same dynamic class loader that is produced by ->TestRecord

3:58 cfleming: rritoch: Right, I'm debugging this now. NewExpr always uses maybeClass, which is basically Class.forName()

3:59 rritoch: However when compiling a deftype form, it always calls LOADER.deref() which gives a DCL.

4:02 rritoch: What I don't understand now is how (TestRecord.) works in a normal non-AOT REPL.

4:03 dysfun: that clojure bug pretty much explains it

4:05 cfleming: Not really, it just says "because classloaders"

4:05 It gets weirder.

4:07 If I start a non-AOT'ed REPL, and instead of using nREPL's load-file I do a (require 'classloader.core) from the REPL, both records have their class in the AppClassLoader

4:09 rritoch: Anyhow, I need to give up for now... I tried (.importClass *ns* 'TestRecord (class (TestRecord. nil))) which I really thought would lead to ->TestRecord using the app class loader, but it didn't

4:10 cfleming: Hmm

4:10 rritoch: Anyway, thanks for looking at it

4:10 I need to give up for the moment now too.

4:10 rritoch: It seems that when it comes to classloaders, clojure will do the exact opposite of what you want it to do, every time.

4:10 cfleming: rritoch: Certainly it's not very predictable.

4:11 rritoch: cfleming: If your using gen-classes, I've been able to deal with some of this classloader issues by extending classes with static initializers

4:12 cfleming: rritoch: Yeah, this is actually for a colleague but I'm going to have similar problems myself soon, so I'd like to understand it.

4:12 rritoch: I took on this issue because I'm trying to learn all of in's and outs of clojure classloading because it frequently causes issues, but I still have a ways to go

4:12 cfleming: rritoch: It seems to be a bit of a mess.

4:14 dysfun: it's largely java's fault tbh

4:15 cfleming: dysfun: Mmmmh, I thought so, but this idiosyncratic choice of which loader to use is all Clojure

4:15 dysfun: *nod*

4:15 i can understand why it's the way it is, but it's not helpful

4:40 rritoch: dysfun: I believe I found the bug

4:40 dysfun: (println (clojure.lang.Namespace/areDifferentInstancesOfSameClassName (class (->TestRecord nil)) (class (TestRecord. nil)))) is returning false

4:40 Or I should say "a bug"

4:41 the areDifferentInstancesOfSameClassName should be validating that both classes are using the same classloader instead of just checking =

4:45 dysfun: rritoch: heh, nice find

4:46 rritoch: dysfun: I am not sure though, this is acting wierd still

4:46 dysfun: welcome to the jvm :)

4:47 rritoch: Wow, crazyland

4:48 Let me see if I can paste this someplace...

4:48 dysfun: i've heard it called worse :)

4:48 http://refheap.com/

4:48 clgv: that predicate seems about right

4:50 did you reevaluate the definition of TestRecord?

4:51 rritoch: https://www.refheap.com/94397

4:52 Now that is crazyness if I ever saw it

4:53 Inside the let it reports they are different, outside let context they're reported as the same.

4:54 I'm supposed to be working right now, but I don't deal well with not knowing the solution to a problem

4:55 clgv: rritoch: better restart your repl. they are the same for both evaluation in a fresh repl overhere

4:56 rritoch: is it possible that there are stale class files in your project?

4:56 rritoch: clgv: I'm not running from repl, I'm running via lein compile (:aot :all)

4:56 From repl all of this crazyness goes away

4:57 cflemming's code if loaded via require :reload-all produces the same classloaders, it is only during lein compile that they deviate, at least in my tests.

4:58 dysfun: this has gotten quite interesting all of a sudden

4:58 rritoch: It could be a version issue though, I'm using version 1.5.1 for this test

4:58 I didn't try a newer version of clojure

4:58 * dysfun isn't running anything below 1.6 right now

4:59 rritoch: I get the same offending results with version 1.6.0

5:00 I really have to stash this issue away for later and get to work, but cflemming has uncovered something very odd about the classloading within lein compile

5:00 * echo-area is waiting for transducers in a stable 1.7.0 version

5:01 clgv: rritoch: but run the compiled code via "lein run" by adding a -main and :gen-class to the namespace - then you get "same" both times.

5:01 so is this really relevant for any practical purpose?

5:02 rritoch: I just added an additional -main function and kept the other code as is

5:04 rritoch: clgv: I'm not exactly sure when this would be relevant, I rarely use top-level "let" statements in code

5:05 clgv: rritoch: it seems to be compile time only. when the compiled code is run and the side effects from loading the class are triggered both report "same"

5:06 rritoch: clgv: Yes, and I noticed the dynamicclassloader dissappears at runtime, both use the classloader

5:06 err, the app classloader

5:08 llasram: AOT really doesn't seem to be a feature the clojure/core people use much

5:13 rritoch: Well, I found one more thing, when running lein compile, the non-let version is reporting same for both, and they're both using the same dynamic classloader that is reported in let for ->TestRecord

5:14 So the only time the app class loader is being used at compile time is when (TestRecord. nil) syntax is used within a let statement.

5:16 cfleming: clgv: it's relevant because the multimethod dispatch doesn't work properly, see the refheap

5:17 print-method is called or not depending on how the record class is instantiated

5:17 llasram: They AOT compile datomic

5:17 rritoch: cflemming: Do you really need to be using a top-level let statement in your code?

5:18 cflemming: The crazyness seems to evaporate if you aren't in a let statement.

5:18 cfleming: rritoch: This is just a repro case, it's not the real code

5:19 rritoch: This was giving problems at the REPL, and seems to be related to http://dev.clojure.org/jira/browse/CLJ-371

5:19 rritoch: cfleming: I'm aware of that, but this bug seems to only presents itself within a let statement

5:19 cfleming: rritoch: Mostly I'd just like to understand how the classloading actually works.

5:20 rritoch: cfleming: Same here, I honestly have no idea how the let form changes things, but it narrows the problem down a bit

5:22 cfleming: Did you see the pastebin I posted?

5:22 cfleming: rritoch: Yes, I'm looking at it now

5:22 rritoch: err, refheap

5:23 It is simply another perspective on the same issue, but the let binding seems to be the basis for the bug

5:24 cfleming: So that different instances check looks legit to me

5:24 I think the difference in the output is because you're getting the classes looked up in different classloaders

5:25 clgv: cfleming: multimethod dispatch in AOTed namespace does not work?

5:25 rritoch: cfleming: Yeah, I was wrong about that function having a bug

5:25 SagiCZ1: clgv: not that i am an expert or anything but it seemed to work in my case

5:26 cfleming: clgv: Take a look at https://www.refheap.com/94392

5:26 You can see there that the print-method method is invoked, or not, depending on how the record class is instantiated.

5:27 Presumably because the classes are different due to different classloaders being used, and the multimethod is dispatched on the Class

5:28 instance? would also fail

5:28 clgv: cfleming: yes I had that running

5:29 llasram: cfleming: Oh yeah. Good point :-)

5:29 (re: datomic; catching up)

5:31 clgv: cfleming: but the multimethod dispatch works in a -main function with the compiled class files in a uberjar

5:31 cfleming: clgv: So multimethod dispatch works fine, it's the class lookup that's a little unpredictable

5:32 clgv: interesting.

5:33 clgv: My colleague was having problems in a REPL because of this. I assume (but I'm not sure) that he'd loaded the AOT code and was then trying to redefine a class.

5:33 Which looks sort of like CLJ-371 but not quite.

5:38 simao: hey any reason why `lein run` would never stop? I am just outputting some strings but lein run gets stuck doing nothing

5:38 llasram: simao: "Never stop" meaning "not exit once the entry-point function returns"?

5:39 simao: yeah, when -main returns

5:39 llasram: simao: Probably the agent thread pool, which uses non-daemon threads. Try adding a call to `shutdown-agents` right before returning from your `-main`

5:41 simao: llasram: nothing changes, still hung

5:42 llasram: simao: Well, are you perhaps starting threads some other way?

5:42 simao: llasram: no, it's very simple what I am doing.. maybe some import is starting some thread but that would be weird

5:42 llasram: simao: code?

5:43 simao: llasram: I just found it. some call to a library was opening a tcp connection and probably would use some threads

5:43 thanks!

5:43 llasram: well, cool

5:44 Hope that actually helps then :-)

5:47 cfleming: I think it's the same problem, just in a more complicated way, combined with how Clojure evaluates code form-by-form

5:48 cfleming: I'm failing to find why, but there's especially tricky interactions which lead to why the `deftype` and `defrecord` macros produce forms which wrap their contents in a top-level `let` instead of `do`

5:48 Since the compiler special-cases a top-level `do` to evaluate each sub-form as independently at the top level

5:53 dysfun: ohh, that's how it does it

6:01 Empperi: ok, this is wierd

6:01 I set :test-paths ["test/clj"] in my project.clj but leiningen doesn't seem to be compiling those into classpath so that those tests could be executed

6:01 what am I missing?

6:03 mavbozo: any good explanation about AOT in the web?

6:10 llasram: mavbozo: Sure. github.com/clojure/clojure/.../Compiler.java ;-)

6:10 mavbozo: (by which I mean: "unfortunately not")

6:10 clgv: mavbozo: depends on your question

6:11 llasram: Empperi: Not sure what you mean by "compiling those into classpath"...

6:12 Empperi: Does the directory hierarchy underneath your test path(s) still reflect the Clojure namespace hierarchy and match the `ns` forms in your test files?

6:13 mavbozo: clgv: like why we should AOT compile some namespace and not the other, or why there are some libraries that come AOT compiled

6:14 llasram: mavbozo: Clojure AOT is for applications. Libraries should *never* be AOT-compiled

6:15 mavbozo: You can get a startup-time speed up with AOT, but most people to use AOT because they think they need executable uberjars, which requires an AOT class

6:15 But you really don't :-)

6:15 Empperi: llasram: yes

6:15 llasram: s,people to,people seem to,

6:16 Empperi: but strangely enough, if I just removed :test-paths declaration it works o_O

6:16 dysfun: "but you really don't" ?

6:16 Empperi: oh well

6:16 it works -> carry on

6:16 llasram: Empperi: noooo

6:16 mavbozo: llasram: but, there is this kind of suggestion https://github.com/yogthos/Selmer/pull/67

6:17 to AOT compile selmer.node

6:17 llasram: That actually doesn't make sense. Could you refheap your project file, the result of the shell command `find test/`, and the path+`head` of one of your test files?

6:17 clgv: dysfun: yes, you can use the pattern of lein-otf to have a fake main class that is AOTed and loads your real main dynamically. so you actual code does not need to be AOT compiled

6:18 TEttinger: is lein-otf even compatible with recent lein?

6:18 mavbozo: llasram: and actually namespace selmer.node in selmer is aot compiled https://github.com/yogthos/Selmer/blob/master/project.clj

6:18 llasram: mavbozo: They are wrong and about to break their users when they release this :-)

6:19 mavbozo: llasram: it's already released yesterday i think in version 0.7

6:19 llasram: (I think -- yogthos should know better)

6:19 Yeah -- just one sec while I verify something

6:19 dysfun: clgv: ah i see. i tend to just do a very quick wrapper around another namespace

6:19 this will save some typing

6:21 llasram: mavbozo: Ok, nm. Last time I checked doing an AOT meant transitively compiling clojure.core, but that seems not to be happening here

6:22 mavbozo: BUT

6:22 mavbozo: IMHO they did the wrong fix

6:23 Actually, I'm going to pause blathering as I don't actually understand what the problem was

6:24 They require selmer.node in selmer.parse, which should define the relevant types. AOT should be completely irrelevant

6:26 mavbozo: llasram: i'll ask yogthos when he's here. including why there is gen-class in that selmer.node

6:26 clgv: dysfun: well, I dont mean to say you should use lein-otf - it broke with recent leiningen. but you can use the same pattern

6:27 mavbozo: why aot'ed libraries might break user's applications?

6:28 llasram: mavbozo: Because of the transitive compilation issue. In the past there have been AOT libraries which unintentionally transitively compiled -> included other libraries

6:29 The Clojure class loading strategy prefers available AOT versions of things. This caused incomprehensible behavior like getting a version of library nothing seemed to include

6:29 mavbozo: They're avoiding that here, although I still think it shouldn't be necessary

6:29 It might be linked to how they're reaching into the protocol implementation to use the protocol backing JVM interface.

6:31 mavbozo: llasram: oh, a library jar which includes other libraries jar

6:31 llasram: Exactly

6:34 mavbozo: thx llasram

6:34 (inc llasram)

6:34 lazybot: ⇒ 41

6:36 mavbozo: the pain of making and using libraries reminds me of old thread https://groups.google.com/forum/#!topic/clojure/WuS31RSiz_A

6:59 justin_smith: szymanowski: ##(filter (set '(a b c)) '(a b d c e b a)) something like this?

6:59 lazybot: ⇒ (a b c b a)

7:06 Fender: today a performance question: I have a vector and a function and I count how often this function is truthy on each element in the vec

7:07 I actually traverse the (range (count values)) via reduce where values is the vector

7:07 and inc an Integer if (function (get values i)) is truthy

7:08 however, now I want to do this for two integers because I got two functions

7:08 meaning I could (reduce some-counting-function [0 0] (range values))

7:08 (range (count values)) that is

7:09 of course, I wouldnt use a persistent vector because that's expensive, instead I tried an int-array

7:09 but thats twice as expensive as counting just one function

7:10 the functions btw are just keywords on a record, so I suppose they're cheap

7:10 is there a faster way to count if <n> functions hold over the same vector?

7:11 that is: is there a fast way to count how often <n> functions hold in one single vector?

7:12 like transient vectors (didnt try), AtomicInteger, int-array (same perf as AtomicIntegers), ...=

7:12 clgv: Fender: as long as you use (range) the other performance optimizations do not make that much sense

7:12 Fender: I read a lot that seq on the vector wouldnt be faster

7:12 you mean I should loop

7:12 of course

7:13 thanks already, sometimes you optimize the wrong thing

7:13 clgv: Fender: if you want fast arithmetic (e.g. for counting) use loop-recur and make sure there is no boxing

7:13 Fender: you're completely right, I now see how stupid that was^^

7:14 noncom|2: how do i get http://mvnrepository.com/artifact/org.apache.commons/commons-io/1.3.2 with deps in project.clj ?

7:15 i tried [org.apache.commons/commons.io "1.3.2"] but it does not work

7:15 ucb: shouldn't it be commons-io though?

7:16 hyPiRion: yeah, it's moved

7:16 clgv: noncom|2: thats probably because mvnrepository is not mavencentral and thus not in the list of your repositories

7:16 hyPiRion: use [commons-io/commons-io "2.4"]

7:16 noncom|2: oh..

7:16 it is even 2.4 now...

7:17 yeah, this one works

7:17 thanks

7:22 Fender: is there a neat way to make sure there is no autoboxing? cantor is not supported anymore and set-warning on reflection doesnt tell me anything...

7:25 justin_smith: Fender: 1.7.x (still in alpha) has warning on boxing if you turn on *unchecked-math*

7:26 Fender: there is also the primitive-math lib https://github.com/ztellman/primitive-math

7:27 Fender: ok, thanks, I will use the latter

7:27 clgv: Fender: warn on reflection should tell you at least for the loop parameters

7:27 justin_smith: clgv: it will tell you if it reflects on their class, but not if they get boxed

7:28 it will happily let an object be java.lang.Long

7:28 Fender: hmm, sometimes during compilation I remember I read some autoboxing warning

7:29 but it was from leiningen

7:29 justin_smith: Fender: leiningen is just running the compile command, I am sure it's the compiler giving the actual warnings

7:30 clgv: justin_smith: it'll tell you the loop params initialized with primitive get boxed before passed to recur

7:30 justin_smith: clgv: oh, cool

7:31 clgv: 1.7 has a new option for *unchecked-math* where you can enable warnings

7:33 Fender: so the absence of a compiler warning for the loop params in 1.6 implies the absence of autoboxing

7:33 justin_smith: Fender: as long as you hinted the arg as a primitive

7:34 if you didn't hint it as a primitive, you'll get no warning

7:34 clgv: Fender: if the arg is initialized with a primitive, yes

7:35 hints will lead to a compile error if I remember correctly

7:35 Fender: e.g. (loop [i 0 ...] ...) or (loop [i (long x) ...] ...)

7:35 Fender: ok, I coerce them as in http://clojure.org/java_interop#Java Interop-Type Hints

7:36 and there is no warning

7:36 but I only inc them, so maybe it sticks to the type in this case

7:38 ok, inc doesnt seem to be type-true

7:38 but inc' is

7:38 so I get a compiler warning if I use inc' but not if I use inc

7:38 jmglov: Hi all! Is anyone awake who knows a bit about Ring?

7:40 kungi: jmglov: what is your question?

7:41 jmglov: I would like to deploy a Ring app (made with lein uberwar) to Tomcat, but using the WebSocketServlet API, not the HttpServlet one.

7:41 As far as I can tell, Ring can't currently do that.

7:41 Am I correct in this?

7:42 kungi: jmglov: my ring expertice is not good enough to answer that question.

7:42 justin_smith: jmglov: I suspect it will be easier to make a standalone uberwar, using httpkit or aleph

7:43 jmglov: how badly do you really need to be using tomcat?

7:43 jmglov: Pretty badly, I think.

7:43 Otherwise, I'd just use http-kit and be done with it. :)

7:44 justin_smith: google immediately finds you asking questions about this on stackoverflow

7:44 lol

7:44 jmglov: I need to deploy to AWS Elastic Beanstalk.

7:44 justin_smith: Yup.

7:45 clgv: ,(binding [*warn-on-reflection* true] (eval '(fn [n, x] (loop [i 0, s 0] (if (< i n) (recur (inc i) (+ s x)) s)))))

7:45 clojurebot: #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)>

7:45 jmglov: I figured #clojure might be able to bring more expertise to bear quickly.

7:45 clgv: Fender: try that one on your repl ^^

7:45 jmglov: I see now that Elastic Beanstalk can do Docker, so perhaps http-kit + Docker would be an option.

7:47 justin_smith: jmglov: that's a nice new option. I have had success with just using plain ec2 instances as well for what it's worth.

7:47 just scp an uberjar and fire it up.

7:48 jmglov: justin_smith: I have done the same with other Clojure services on EC2, but Elastic Beanstalk gives me ELB and Auto Scaling as well, which saves quite a bit of work.

7:49 Otherwise, I'd need some tool to deploy new versions to all running instances, update my AMI, etc.

7:49 So it's quite a lot of tooling that I'd potentially have to write.

7:49 justin_smith: right, clearly you are hitting scale issues I have not seen

7:50 I never had scaling issues that couldn't be fixed with nginx reverse proxy and a varnish layer on a single instance

7:50 jmglov: Yeah, I have to be available and scalable, so I have some constraints that are best left to Amazon to sort out. :)

8:06 TimMc: jmglov: Embedded Jetty doesn't allow you to use websockets? I've never used them myself.)

8:06 justin_smith: TimMc: embedded Jetty doesn't work on elastic beanstalk

8:06 unless maybe with that docker option he mentions

8:07 TimMc: Another thing I know nothing about. :-)

8:07 jmglov: TimMc: I believe that embedded Jetty does handle websockets, though almost no-one seems to be doing that.

8:07 But as Justin says, that doesn't really scratch my itch.

8:08 http-kit on Docker looks like the best way forward, honestly.

8:08 justin_smith: TimMc: the idea with elasticbeanstalk is that the instances are totally generic, with nearly no setup, which allows fast and easy allocation / deallocation of instances as needed

8:08 TimMc: Ah, OK.

8:08 jmglov: But I think I'll take a crack at writing a Ring adapter for WebSocketServlet.

8:09 justin_smith: godspeed, that sounds very useful

8:09 jmglov: The Docker stuff is a lot more complicated than a simple "lein beanstalk deploy production". :)

8:09 I don't think the adapter would really be that complicated. ring.util.servlet is not much code at all.

8:10 Anyway, I'll report back once I've done it or died trying. ;)

8:10 TimMc: There's also that async ring thingum...

8:10 justin_smith: jmglov: I'll take your word for it. The lower I get in the stack, the more likely a small miscalculation totally ruins things, so I am often reluctant to make something like that.

8:11 atankanow: whomai

8:11 TimMc: https://github.com/dgrnbrg/spiral

8:11 justin_smith: haha, you almost got an easteregg

8:11 whoami

8:11 lazybot: justin_smith

8:11 atankanow: haha

8:11 just making sure circe set my nick correctly

8:11 justin_smith: pwd

8:11 lazybot: #clojure

8:11 justin_smith: ls

8:11 lazybot: bin home lib64 lost+found media opt proc root sbin tmp usr var

8:11 TimMc: mutt

8:11 lazybot: Woof!

8:11 atankanow: rm -rf /

8:12 hellofunk: In Om I am trying to udpate parent local state from child. Code snippet is last message in this thread, if anyone spots the problem: https://groups.google.com/forum/#!topic/clojurescript/22Oh2BkGlyQ%5B1-25-false%5D

8:12 atankanow: no wait, sudo !!

8:13 clgv: atankanow: make sure you got the correct window ;)

8:16 atankanow: clgv: never! i type indiscriminately into any application with text input

8:17 jmglov: justin_smith: You're certainly right, but I can't let fear stop me. :)

8:18 Bugs happen and get fixed, no matter where in the stack I am.

9:00 charliekilo: stupid question: am I missing anything about vars pointing to record? Using Prismatic Schema this works (schema/check MySchema {:foo "bar"}), while (schema/check #'MySchema {:foo "bar"}) does not.

9:00 Bronsa: ,(defrecord Foo [])

9:00 clojurebot: sandbox.Foo

9:00 Bronsa: ,Foo

9:00 clojurebot: sandbox.Foo

9:00 Bronsa: ,#'Foo

9:00 clojurebot: #<CompilerException java.lang.RuntimeException: Expecting var, but Foo is mapped to class sandbox.Foo, compiling:(NO_SOURCE_PATH:0:0)>

9:00 Bronsa: ,(class Foo)

9:00 clojurebot: java.lang.Class

9:00 Bronsa: charliekilo: records are classes, not vars

9:01 justin_smith: and even if you are talking about a var ##(= #'+ +)

9:01 lazybot: ⇒ false

9:02 justin_smith: Guest35729 is spamming

9:02 charliekilo: Bronsa: but wouldn't (def MySchema (schema/either ...)) create a var?

9:02 justin_smith: charliekilo: see my point

9:03 on the other hand ##(= + @#'+) does work

9:03 lazybot: ⇒ true

9:03 justin_smith: but it's also silly :)

9:05 charliekilo: so I need to basically resolve the class then and not the var

9:05 justin_smith: well, schemas are by convention in CamelCase but are not classes, they are vars holding clojure data structures

9:06 unless you are talking about something actually made with defrecord or such

9:06 jonathanj: hrm, is anyone familiar with Liberator?

9:07 ordnungswidrig: jonasen: I am

9:07 jonathanj: how do i dynamically return the Content-Type for :handle-ok ?

9:07 charliekilo: justin_smith you sure, because then I call (class MySchema) it returns schema.core.Either (in my case)

9:07 jonathanj: (like, i've pulled some stuff out of a database and now i know the content type is X)

9:07 charliekilo: which is a class

9:08 ordnungswidrig: liberator figures this out for you based on what the client accepts ("Accept" header) and what the resource provides (:available-media-types)

9:08 justin_smith: charliekilo: how do you define the schema?

9:08 ordnungswidrig: if you want to do that dynamicaly, then specify a function for :available-media-types which returns the type in a vector.

9:09 charliekilo: justin_smith (def MySchema (schema/either ...))

9:09 justin_smith: aha, yeah. in that case MySchema is a var, but the value it points at is an instance of schema.core.Either

9:09 but MySchema is not a class

9:10 so what I was saying still holds. It's in CamelCase but is not in fact a class.

9:14 jonathanj: ordnungswidrig: hrm, is there some handler that is called as a kind of "setup" handler?

9:14 ordnungswidrig: the problem i have now is that my exists? handler places the necessary information into the context but available-media-types runs before exists?

9:15 justin_smith: charliekilo: schema/either returns an instance of a record (schema.core.Either), and records are just specialized maps

9:15 ordnungswidrig: jonasen: well, look it up in :available-media-types and put it into the context there. you can then use that value in :exists?

9:16 jonathanj: ordnungswidrig: i can't mutate context, can i?

9:16 usually i return the map to merge with context from a handler, but in this case i have to also return the vec of media types

9:17 ordnungswidrig: jonasen: let me check

9:17 justin_smith: charliekilo: one thing that can lead to confusion is that #(= (#'+ 1 1) (+ 1 1)) vars are callable, and implicitly deref when called. But they are not generally substitutable with the thing they resolve to.

9:17 oops ##(= (+ 1 1) (#'+ 1 1))

9:17 lazybot: ⇒ true

9:18 justin_smith: also, the CamelCase convention for schema vars is misleading, because usually something in CamelCase in clojure should be a class, not a var

9:19 ordnungswidrig: jonasen: you're right. In this case you would need to specify :media-type-available? and call to `(negotiate-media-type ctx)` yourself. But I guess it's simpler to lookup the resource in `service-available?` which has the nice side effect to produce a good status code in case your db fails :-)

9:19 hellofunk: if you have a destructred arg in a fn and you call that function with nil as the arg rather than something that can be destructured, it this acceptable and you just get nil for your destructured args?

9:20 justin_smith: hellofunk: that is the only behavior you can expect

9:20 hellofunk: justin_smith as opposed to say errors, this would be considered fine?

9:20 justin_smith: ,((fn [{a :a}] a) nil)

9:20 ordnungswidrig: jonasen: would you mind to file an issue to liberator on that? I find it would be a good extension to be able to "update the context" from :available-media-types.

9:20 clojurebot: nil

9:21 justin_smith: hellofunk: destructuring will always nil rather than error unless the syntax is invalid

9:21 charliekilo: justin_smith I followed Prismatic's naming convention (see their README) ... think Prismatic uses CamelCase to highlight its a schema

9:22 justin_smith: charliekilo: right. that's why I explicitly blame the naming convention and not you.

9:22 but it's bound to lead to confusion in forums like IRC where we see CamelCase and assume a class :)

9:23 charliekilo: justin_smith right, I should have been more explicit by highlighting the usage of the Prismatic naming convention

9:23 justin_smith: well, the usage of the word "record" in your question may have led things astray as well

9:24 you asked about a var pointing to a record, when I think you really meant a var pointing to an instance of a record

9:24 jonathanj: ordnungswidrig: thank you for your help, i'll file a bug when i get the chance

9:25 justin_smith: but I think we have it all cleared up at this point what was really going on :)

9:25 ordnungswidrig: jonasen: you're welcome

9:37 charliekilo: justin_smith got it ... thanks

9:43 atankanow: seq is a nice idiomatic way to process possibly empty element collections a la #(if-let [xs (seq %)] (process-collection xs) (process nil))

9:43 borkdude: what's wrong with this Datalog query? https://www.refheap.com/94400

9:43 atankanow: is there a nice way to also handle non-Iterables here ... that is send non-Iterables to the else

9:43 borkdude: the one on line 5

9:43 justin_smith: atankanow: in 1.6 you can also use not-empty, basically the same thing but I think it conveys the intention very nicely, and it keeps the collection type

9:44 ,(map (juxt seq not-empty) [[] [1 2] () '(1 2)])

9:44 clojurebot: ([nil nil] [(1 2) [1 2]] [nil nil] [(1 2) (1 2)])

9:44 atankanow: thanks justin_smith

9:44 jonathanj: is there a function such that (f "abc") returns ["abc"]?

9:45 atankanow: but what if one of the elements is say a boolean

9:45 borkdude: jonathanj vector

9:45 justin_smith: ,(vector "abc")

9:45 clojurebot: ["abc"]

9:45 jonathanj: borkdude: oh, i was trying "vec"

9:45 thanks

9:45 justin_smith: ,(not-empty false)

9:45 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Boolean>

9:45 justin_smith: ,(seq false)

9:45 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Boolean>

9:45 atankanow: basically i want non-collections to be treated as such without explicitly checking =)

9:46 justin_smith: atankanow: you need (and (coll? x) ...)

9:46 or something using a check for coll?

9:46 atankanow: that's what i thought justin_smith ... i just wasn't sure if i was missing a nice clever single fn solution

9:46 borkdude: gotcha: datomic inputs must start with a ?

9:47 justin_smith: but any place where you are maybe getting a single item or maybe a collection indicates to me you are interacting with a poorly designed api

9:47 atankanow: agreed

9:47 justin_smith: or at least a crippled one - what if you wanted a collection as your single item?

10:40 EvanR: ,(quote <)

10:40 clojurebot: <

10:40 EvanR: ,(quote :)

10:40 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :>

10:40 EvanR: :(

10:40 ,(quote ::)

10:40 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: ::>

10:41 EvanR: ,(symbol ":")

10:41 clojurebot: :

10:42 mikerod: EvanR: the symbol constructor allows a lot of symbols to be created that aren't readable

10:43 EvanR: is this bad

10:43 mikerod: ,(symbol " h ")

10:43 clojurebot: h

10:43 mikerod: I think in order to make the symbol construction performant, it just allows anything in a string

10:43 (this is mostly a guess of mine)

10:43 EvanR: are unreadable symbols bad, like (symbol "<:")

10:44 mikerod: ,<:

10:44 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: <:>

10:44 mikerod: EvanR: I don't know. I guess it depends on what you intend to do with them.

10:44 They are bad if you intend for them to be read. :)

10:44 EvanR: hmm, i was using them abstractly. i keep forgetting symbols are really about the runtime environment

10:45 mikerod: EvanR: Yeah, I find it awkward to use them for anything other then their intended runtime semantics.

10:45 Since they have meaning already tied to them there. I'd suppose it should be considered bad practice to use them for other

10:45 things.

10:47 Keywords are much better suited for representing something as itself with no other meanings tied to runtime behavior.

10:48 EvanR: right keywords are good.. for words

10:48 but prefixing other symbols with : is awkward

10:49 :<:

10:49 :?e

10:49 justin_smith: you can always use get, and a string

10:50 EvanR: get and a string?

10:50 justin_smith: (get {"a string" 1} "a string")

10:50 ajmccluskey: Is it possible to extend a protocol in the same sense as extending a Java interface? From what I can see it isn't, but it seems like it makes sense to express hierarchies of behaviours.

10:51 e.g. A "Graph" protocol expects implementers to be able to add-node, add-edge, etc.

10:51 justin_smith: EvanR: many people are over eager to take incoming data (for example in an http request, or sql results, or json) into symbols or keywords, where really things are simpler if they remain strings

10:52 ajmccluskey: A "WeightedGraph" protocol might add the ability to add-weighted-edge, but a WeightedGraph should be able to do all the things a "Graph" can do as well

10:52 EvanR: well this isnt incoming data its symbols in a dsl

10:52 like datomic usage of '?e

10:52 justin_smith: ajmccluskey: you can implement a Weighted protocol, and then document that a client should implement both Graph and Weighted. This is the general approach in clojure.core

10:53 EvanR: in that case, use symbols or keywords that aren't insane :)

10:53 if it isn't client provided, that's in your power

10:53 EvanR: thats what im ascertaining, colon is an insane symbol in clojure

10:53 <: is standard notation for subtype

10:54 justin_smith: EvanR: tailing colon is OK

10:54 ,'<:

10:54 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: <:>

10:54 EvanR: nope

10:54 justin_smith: err, not

10:54 sorry

10:54 my bad

10:54 ajmccluskey: justin_smith: Right. That's what I was seeing, hence I assumed it wasn't possible. Feels like it would be better to capture this in code rather than comments.

10:54 justin_smith: ajmccluskey: clojure is opinionated against inheritence, this is reflected many places in the design

10:56 ajmccluskey: justin_smith: I knew it was opinionated against inheritance of implementations, but I guess I see legitimate reasons for inheritance of interface.

10:57 EvanR: prerequisite interfaces for an interface would be good

10:57 protocols on a protocol

10:58 justin_smith: ajmccluskey: there is no manner of enforcing that an interface is fully implemented. Putting it all in one interface vs. mixing multiple interfaces gains you very little, because nothing prevents incomplete implementation.

10:59 EvanR: same goes for that argument. Since I can't even enforce that you implement all the methods in one interface, how does mixing multiple interfaces into one give me any net benefit?

10:59 ajmccluskey: justin_smith: I assumed it would be a compilation error to only partially implement a protocol/interface

10:59 EvanR: i wasnt mixing, but also, you can "just not implement" part of an interface?

11:00 justin_smith: not at all

11:00 EvanR: nothing makes you implement a full interface.

11:00 EvanR: in any case, why make an assumption that someone might do that

11:00 justin_smith: EvanR: it's common.

11:00 EvanR: even if they implement all the methods, you also have no guarantee they did it right

11:00 doesnt seem to be "our" problem as the protocol user

11:01 justin_smith: sure, but what I am saying is that interface inheritence gains you complexity, but doesn't actually help you simplify anything. It doesn't do anything useful.

11:02 whether you are implementing one interface, or many, you actually have to go and look at the interface(s) and figure out what you need to implement.

11:02 the compiler isn't enforcing any of it

11:02 ajmccluskey: In the context where full implementation of protocols/interfaces isn't required it doesn't do anything useful. I'd be interested to find out why the decision was made to not enforce full implementations.

11:03 I guess the one gain I can think of in this context is that it's expressed semantically as code rather than in a comment, which maybe makes it stand out more. There's also the possibility for adding tooling/checking around it.

11:03 EvanR: what i was thinking of was, you want to implement an independent protocol B for class X, class Y, and for anything implementing protocol A (ignoring for the moment what happens if X or Y implements A)

11:04 justin_smith: ajmccluskey: because needing full implementations creates a lazy path leading to inheritance. And lazy partial implementation is much easier to fix than lazy / poorly thought out inheritence trees.

11:04 laziness as in "what does a programmer in a hurry / with other priorities end up implementing"

11:05 EvanR: its common in a dynamic system to treat it as if people are following some sanity rules, if they dont, its their problem

11:05 two different subjects it seems

11:06 mushing several independent interfaces into one seems bad

11:07 justin_smith: implementing a protocol based on another protocol leads to the ruby problem "where the hell is the code that generates this behavior exactly?"

11:08 EvanR: shouldnt the system tell you which implementation is being used for a given class and protocol pair

11:08 ajmccluskey: justin_smith: good points

11:08 EvanR: in file foo on line bar

11:08 also ruby does not have anything close to anything we are talking about

11:08 ajmccluskey: EvanR: interesting point about dynamic systems giving people more freedom. Agree.

11:09 EvanR: ajmccluskey: the only way i can do anything in super dynamic language x is to do tons of static checks in my head, i think its common for library designers to treat users as following some unseen protocol

11:10 which they can use to write their code correct against some standard

11:10 justin_smith: EvanR: I am talking about the more general design problem of implementation being spread in unintuitive ways. Which ruby code in my experience often has in spades, and meta-protocols would lead to similar problems.

11:11 EvanR: this is why I like prismatic/schema now that I have started using it

11:11 EvanR: even if I never run the schema checks, just having the annotations on my functions is great

11:12 EvanR: yes so maybe the gripe is about using implementation somewhere for something without some visible code to tell you whats going on

11:12 or how / why its even happening in this context

11:13 Bronsa: justin_smith: not being able to extend a protocol to a protocol leads to this https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/core.cljs#L8164-L8260

11:13 justin_smith: Right. And inheritence, and nesting of protocols on protocols (effectively inheritence) are big causes of that. One of my favorite things about clojure is how easy it usually is to intuit where the behavior I am observing is likely implemented.

11:14 EvanR: but the using a protocol to implement a protocol is in my mind equivalent to using a function to implement another function

11:14 Bronsa: and juuio is the daily spammer.

11:14 EvanR: "function inheritance" is usually not considered bad

11:15 justin_smith: EvanR: than do what you would do with a function, and wrap one in calls to the other. Protocols are allowed to call methods on other protocols.

11:15 EvanR: you follow the (visible) code to find out why something is working

11:15 justin_smith: thats what im talking about

11:16 justin_smith: EvanR: I thought you were talking about extending Protocols onto other Protocols

11:16 EvanR: protocol P implementation X using the method from P2 implemented on X

11:16 P implementation Y wouldnt

11:17 and from there you could make it polymorphic, instead of just X, any x that has P2

11:17 or copy the code, which is what ive been doing in this case

11:17 since the code is identical

11:19 justin_smith: Bronsa: yeah, that is the downside, I admit

11:19 Bronsa: what do you think the right way to do it would be?

11:20 EvanR: just looked at that link

11:22 for whatever common protocol (most of) those interfaces use to implement IPrintWithWriter, call it P, implement IPrintWithWriter *for P*

11:23 Bronsa: justin_smith: I don't know of a good way to avoid that that doesn't include some use of inheritance

11:23 EvanR: but without enforcement, you will have a confusing rule to disambiguate the case of overlapping implementations

11:23 what im saying isnt inheritance

11:25 Bronsa: justin_smith: note that since in clojure those protocols are actually interfaces, we *can* extend a protocol to them -- with the caveat that in the case of overlapping implementations one at random will be selected

11:25 EvanR: :(

11:26 so dont overlap

11:27 justin_smith: EvanR: given that this is the jvm, how would you extend an interface onto another interface without inheritance?

11:27 Bronsa: justin_smith: but since most of the clojure interfaces form a hierarchy, there's rarely this issue. extending IPersistentMap will win over IPersistentCollection and Seqable etc

11:28 justin_smith: Bronsa: is there a trick for that? because we were talking about this recently and I tried extending a protocol onto another protocol and it just didn't work, maybe I was doing it wrong

11:28 EvanR: justin_smith: well not being able to implement it for some technical reason is a different story from its a bad idea

11:28 justin_smith: Bronsa: a trick for extending protocols to protocols that is

11:29 Bronsa: justin_smith: in clojure?

11:29 justin_smith: EvanR: yeah, I think I had a "clojure stays close to the impl" premise that we weren't sharing

11:29 Bronsa: yeah

11:29 Bronsa: justin_smith: in clojure you can use the underlying interface of a protocol

11:29 justin_smith: but this will only work for types that implement that protocol inline

11:29 justin_smith: ahh, so not via extend-protocol

11:29 no wonder it didn't work

11:30 thanks

11:31 puredanger: cfleming: I saw your questions in the backchat - you are probably running into this gem: http://dev.clojure.org/jira/browse/CLJ-979 which would be great to fix

11:34 Bronsa: there's an even weirder one

11:35 but I can't find the ticket

11:36 puredanger: Bronsa: justin_smith: fwiw, I find the non-ability to layer protocol abstractions to be very frustrating as well. I've asked Rich about it in the past and he didn't seem to have strong feelings either way iirc.

11:36 Bronsa: maybe this AOT one: http://dev.clojure.org/jira/browse/CLJ-1544 ?

11:37 Bronsa: puredanger: no it had to do with redef'd deftypes & #ctor[] syntax

11:37 puredanger: doesn't ring a bell

11:38 gfredericks: puredanger: do you know if there's any general guidance around the use of custom data literals/readers in [contrib] libraries?

11:38 I was thinking of making a clojure-dev email about this but that's a lot of effort :)

11:38 puredanger: as far as whether they're ok?

11:38 gfredericks: in particular including a data_readers.clj file

11:38 and the implications of that happening in a library

11:39 puredanger: they were designed for use by libraries, so I would think that is ok

11:39 make sure to namespace your tags of course

11:39 gfredericks: yeah; how verbose should a namespace be? e.g. for test.check

11:40 reiddraper: com.gfredericks.is.a.swell.programmer.random.aes

11:40 justin_smith: are multiple data_readers.clj files reliably loaded, even though they all have the same classpath-relative location?

11:41 Bronsa: puredanger: http://dev.clojure.org/jira/browse/CLJ-1495

11:41 gfredericks: justin_smith: looks like core.clj intends to load all of them

11:41 via (.getResources class-loader "data_readers.clj")

11:41 puredanger: Bronsa: right. I don't think that's AOT-related though

11:41 justin_smith: cool

11:41 gfredericks: justin_smith: and leiningen intentionally merges them when doing uberjars

11:41 puredanger: gfredericks: it's 'sposed to work!

11:41 Bronsa: puredanger: the incredibly weird thing is that in the last example, if you don't evaluate "#user.Foo[1]" the (Foo. 1) call will use the updated type

11:42 hiredman: fyi, I am already squatting bytes/*

11:42 Bronsa: puredanger: no definitely a classloader issue. but I honestly think CLJ-979

11:42 and a lot of other "AOT bugs" have to do with the classloader rather than with AOT

11:42 puredanger: hiredman: ideally, should be something a little more tied to the library

11:42 Bronsa: no doubt

11:43 gfredericks: puredanger: alrighty I'll go ahead with that using the "clojure.test.check" namespace

11:43 puredanger: thanks!

11:43 hiredman: pfffft

11:43 puredanger: gfredericks: I hate to use anything that long, but I'm not sure how else you end up with a manageable ecosystem? probably just test.check would be fine

11:44 hiredman: which lib is bytes/* for ?

11:44 mavbozo`: puredanger: is stuartsierra 's suggestion in this old mailing list thread still relevant? https://groups.google.com/forum/#!topic/clojure/B4_uGy1VhnA

11:44 "data_readers.clj is intended for application developers. Libraries may define data reader functions and suggest tags for consumers of that library" - stuartsierra

11:45 stuartsierra: Ignore me

11:45 KnightsWhoSayNi: /ignore stuartsierra

11:45 stuartsierra: Don't use data readers in code.

11:45 If you have an EDN data file with custom tags, that's fine.

11:45 hiredman: puredanger: https://github.com/hiredman/bytes

11:46 sm0ke: HEY GUYS

11:46 puredanger: well at least it matches the project name :)

11:46 sm0ke: oops sorry for the caps

11:46 gfredericks: stuartsierra: do you still object to a library providing data_readers.clj for something specific to that library (using namespaced tags)?

11:46 stuartsierra: gfredericks: yse

11:46 sm0ke: is there a way to print bytes as readable edn?

11:47 stuartsierra: There's almost never any good reason to make data-literal tags globally visible to all code. A function or macro can do the same job and the semantics are clearer.

11:47 Again, if you're using it for custom data types in EDN files, that's fine, just pass your custom readers in a map to clojure.edn/read

11:47 gfredericks: stuartsierra: this is for a functional PRNG

11:48 which would be nice to be able to print/read transparently

11:49 especially for repl stuffs

11:49 stuartsierra: I don't think "transparent" (de)serialization is achievable with print/read.

11:49 gfredericks: what's the downside here?

11:49 stuartsierra: There are too many edge cases, it's easier just to extend EDN in the specific places you want to use it.

11:49 mavbozo`: gfredericks: for applications such as datomic, maybe there is a very good reason to include it's own data_readers.clj

11:50 stuartsierra: Even in Datomic, we've had to educate users not to use data literals like #db/ident in code, because they're evaluated only once at read time, which is almost never what you want.

11:50 gfredericks: a prng could be print-dup-able without much trouble

11:52 justin_smith: gfredericks: idea being that a literal would specify a seed, so at read time it would be reset to that seed?

11:52 stuartsierra: Maybe. I hope someone can prove me wrong. So far my experience with tagged literals has been almost as bad as AOT-compilation.

11:52 So now I'm scarred and just tell people "don't go there."

11:52 gfredericks: justin_smith: it's a pure value, so seed & state sure

11:53 justin_smith: gfredericks: what differentiates a seed and a state in a prng?

11:54 gfredericks: it's just terminology; "entire pertinent internal state" is what I was getting at

11:54 where state is the functional immutable sense of the word

12:02 sm0ke: juuio: is a spam bot

12:02 arrdem: we seem to be missing technomancy's fingerguns

12:03 $seen technomancy

12:03 lazybot: technomancy was last seen talking on #leiningen 17 hours and 15 minutes ago.

12:03 justin_smith: arrdem: yeah, I think we need someone with the right privs to deputize some more sherrifs via chanserv

12:03 rhickey, maybe chouser, can do that

12:04 puredanger_: we had this discussion this week. the next time I can talk to rhickey or chouser, I will.

12:04 arrdem: ohai puredanger_

12:04 puredanger_: why I am both puredanger and puredanger_ right now, I don't know :)

12:05 sm0ke: somehow since morning today i am getting jinxed a lot with other people!!

12:05 a lot!! which is kind of creepy

12:05 gfredericks: stuartsierra: I should probably take it to clojure-dev then?

12:06 justin_smith: puredanger_: /msg nickserv ghost puredanger <password>

12:06 sm0ke: right now i was asking for printable edn bytes representation

12:06 and some just posted https://github.com/hiredman/bytes before i could ask!

12:06 arrdem: /kick puredanger_

12:06 EvanR: is postwalk lazy?

12:06 puredanger: test

12:07 justin_smith: arrdem: that works? for some reason I thought nickserv was needed for that

12:07 Empperi: ,(type (clojure.walk/postwalk inc [1 2]))

12:07 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.walk, compiling:(NO_SOURCE_PATH:0:0)>

12:07 Empperi: darn

12:07 clgv: EvanR: no. how could it walk maps & co if it were? ;)

12:07 justin_smith: EvanR: I don't think it can be, since it can return a hash-map

12:08 EvanR: well that sort of makes sense.

12:08 but the IO error does not occur until i pprint the hash map

12:08 i can show the keys but not the values

12:08 gfredericks: sm0ke: hiredman: I've been using whidbey for repl pprinting and it includes its own bytes printer :/

12:08 puredanger: EvanR: lazy value?

12:08 justin_smith: EvanR: well, you can have lazy functions inside the postwalk, that don't get forced neccessarily

12:09 EvanR: bingo

12:09 justin_smith: but that's not postwalk being lazy, per-se

12:09 puredanger: if only you had transduced :)

12:09 EvanR: there is a single "map" in the code, im guessing that is it

12:10 mdrogalis: Aside from IFn and Clojure, is there anything in particular that needs to be done before invoking a Clojure fn from Java?

12:10 Running up against: java.lang.IllegalStateException: Attempting to call unbound fn

12:10 Both the Clojure and Java code are in the same uberjar.

12:11 clgv: mdrogalis: using the public API e.g. the `var` method should be safe

12:11 mdrogalis: clgv: What do you mean by safe?

12:12 puredanger: mdrogalis: you should initiate the runtime by ensuring that clojure.java.api.Clojure is loaded

12:13 (which really loads RT importantly)

12:13 mdrogalis: puredanger: Yep, I imported that, as well as clojure.lang.IFn.

12:13 puredanger: import does not load

12:13 calling Clojure.var() or something else will

12:13 mdrogalis: D'oh!

12:14 clgv: IFn f = Clojure.var("my.lib/my-fn"); is the path to go

12:14 puredanger: right

12:14 llasram: + `require` the namespace for non-clojure.core

12:14 mdrogalis: Actually, looks like I have that covered as well: IFn commission = Clojure.var("my-ns", "my-fn");

12:15 puredanger: http://clojure.github.io/clojure/javadoc/clojure/java/api/package-summary.html

12:15 hiredman: gfredericks: I am so beyond base64 these days

12:15 mdrogalis: llasram: There we go, that'll do it I think.

12:15 puredanger: hiredman: base65

12:15 hiredman: https://github.com/hiredman/base85

12:15 mdrogalis: puredanger: I didn't read down far enough :) Got excited and coded after I saw "invoke"

12:15 gfredericks: hiredman: yeah I was trying to check if the first and second halves of my array were the same and base64 was no help

12:16 mdrogalis: Thanks guys.

12:16 puredanger: mdrogalis: http://tech.puredanger.com/2007/07/11/miller-principle/

12:16 cfleming: puredanger: Thanks, that does look like it.

12:16 puredanger: cfleming: we spent a fearful amount of time fighting that issue at Revelytix

12:17 mdrogalis: puredanger: I got half Miller Time'd. :P

12:17 puredanger: mdrogalis: oof

12:17 llasram: cfleming, puredanger, Bronsa: I vaguely recall an IRC conversation where Bronsa figured out the cause of that issue, but maybe I was hallucinating

12:17 puredanger: cfleming: the workaround we found at the time was to compare classes by name, not Class

12:18 llasram: if anyone has figured it out, it would be Bronsa :)

12:18 cfleming: puredanger: So you'd dispatch your multimethod on the class name?

12:18 justin_smith: there is also base-_SEMI_lkjfdsa https://www.refheap.com/90612

12:19 puredanger: cfleming: I'm not saying it's pretty :)

12:19 cfleming: puredanger llasram: No doubt, my money is on Bronsa :)

12:20 Which classloader is used when seems like black magic, after looking at the code a little.

12:20 llasram: Rich's commit comment when using the `(let [] ...)` instead of `(do ...)` is "prevent dynamic classes from being flushed before use"

12:25 hiredman: because toplevel do's get hoisted

12:27 puredanger: I don't have time to look at this right now but if there was a solution to it I would be happy to lobby for getting it into 1.7.

12:33 TimMc: hiredman: I'm partial to base256 myself

12:34 hiredman: you've gone too far!

12:34 TimMc: base257

12:36 Hmm, I don't see technomancy. I guess I'll just get spammed.

12:37 llasram: base128, for encoding in signed bytes

12:41 cfleming: puredanger: Ok, I'll take a look with my colleague and see what we can see. I suspect time will be short for both of us too.

12:45 kenrestivo: aviso pretty print would be great... if only i could figure out how to turn off the dang colors

12:49 cause, you know, https://www.refheap.com/94410

12:51 hah, i found a hack: use timbre error log, since i already have timbre configured :fmt-output-opts {:nofonts? true}

13:07 are there any examples of what buf-fn needs to be in core.async/pub ? i naively gave (async/pub c :topic (async/buffer 1000)) and it was expecting a fn, so i tried (async/pub c :topic async/buffer), no dice either.

13:10 Bronsa: puredanger: I think I have fixed both clj-979 and clj-1495

13:11 here's a preview of the patch http://sprunge.us/YddP?diff

13:11 llasram: Bronsa: !!!

13:12 So obvious once you point it out

13:12 Bronsa: the tl;dr is that Class.forName was ignoring the classcache of dynclassloader

13:13 puredanger: hmmm.. sounds promising

13:13 Bronsa: tests are passing, as well as the testcases from the 2 tickets

13:15 puredanger: I've got other focus today but whatever you can do to clean that up for more evaluation would be great

13:15 Bronsa: yeah sure, I'll clean it up and attach it on the ticket

13:15 puredanger: if I'm going to try to get it into 1.7, I will need to mount a compelling case :)

13:15 llasram: (inc Bronsa)

13:15 lazybot: ⇒ 74

13:16 puredanger: things that would help: super clean ticket+patch. votes. test runs on external libs. knowledge of cases where people have had to maintain a fork of Clojure to get around it. etc

13:17 kenrestivo: there were two people here last night banging their heads against this IIRC

13:18 puredanger: yes, that was the start of this thread

13:19 kenrestivo: that's amazing how fast it got diagnosed and, apparently, fixed

13:19 (inc bronsa)

13:19 lazybot: ⇒ 75

13:19 puredanger: (inc bronsa) ;indeed

13:19 lazybot: ⇒ 76

13:21 puredanger: there may be other jiras out there that this affects as well

13:22 Bronsa: I remember having a long mail convo with ambrosebs about this issue months ago, IIRC he hit this bug aswell with core.typed

13:23 puredanger: CLJ-1544 perhaps ?

13:24 Bronsa: puredanger: just tested that seems unrelated as it's still throwing

13:24 puredanger: I believe CLJ-1544 might be related to the ticket hiredman opened about the classloader being popped

13:25 puredanger: yeah

13:25 CLJ-1457

13:25 sdegutis: look, I don't know about you, but metadata is probably my favorite way to use Clojure

13:25 Bronsa: I hate metadata.

13:25 sdegutis: why?

13:25 clojurebot: why is the ram gone

13:25 Bronsa: weird evaluation rules

13:26 weird corner cases

13:26 puredanger: +1 on that :)

13:26 Bronsa: mostly around :tag specifically

13:26 sdegutis: Bronsa: i mean purely on vars

13:26 Bronsa: ,(def ^{:foo (println "foo")} a)

13:26 clojurebot: foo\nfoo\n#'sandbox/a

13:26 Bronsa: then there's that.

13:26 sdegutis: I love to do (defn ^:foo ^:bar some-fn [] ...)

13:26 puredanger: don't do that :)

13:27 Bronsa: http://dev.clojure.org/jira/browse/CLJ-1137

13:28 sdegutis: oh wow

13:28 so anyway, metadata is my favorite API

13:28 macros are very limited compared to metadata

13:28 metadata is declarative, macros are transformative

13:28 you cant easily wrap macros, whereas you can easily re-calculate and add metadata

13:28 so far, it is clear to all that we should be using metadata

13:29 Bronsa: ,(meta '^:foo {})

13:29 clojurebot: nil

13:29 Bronsa: there's also this

13:29 sdegutis: naturally, i only mean on vars

13:33 Bronsa: puredanger: I guess I'll sneakily link a couple of jira tickets a day when you're on IRC if that helps getting them triaged :P

13:33 puredanger: heh …

13:34 well not sure that means much :)

13:34 sdegutis: TIL clojure and crosier rhyme

13:35 puredanger: sounds like the start of a song to me

13:36 sdegutis: i learned the word crosier because i was reading about the pope's new lightsaber crosier and the controversy around it

13:36 didnt know how to pronounce it -- looked it up in the dictionary, it has "ZH" in the "s" part

13:36 took a guess, and looked up "closure" -- sure enough, same ZH!

13:36 and we all know Clojure is pronounced the same as "closure"

13:39 puredanger: Bronsa: http://dev.clojure.org/jira/browse/CLJ-1132 ?

13:39 kenrestivo: looks like the game now is to see how many jira tickets can be closed with one bugfix :-)

13:39 maybe a new record could be set

13:40 puredanger: no pun intended

13:40 kenrestivo: haha record

13:41 Bronsa: puredanger: yeah that's likely the same issue

13:41 puredanger: I just marked it as a dupe, almost certainly the same thing

13:41 crash_ep: If I have a byte array that represents a series of Unicode characters, and I know the character encoding of this series, what's the best way to convert the byte array into a seq of code points?

13:41 kenrestivo: really, i've heard people complaining about "broken reload semantics" of records/protocols for a while. i'm using tools.namespace.refresh to get around it, as i'm sure many people are. seems like this would be an epic fix.

13:41 Bronsa: puredanger: I'll test it later, having dinner now

13:41 puredanger: Bronsa: np, greatly appreciate your help

13:49 pbomb: Would someone mind taking a peek at this http://bit.ly/1CJthES and letting me know if I'm barking up the wrong tree?

13:49 The actual question is in the bottom paragraph.

13:49 Frozenlock: Any good libraries to sanitize form inputs? I tried https://github.com/alxlit/autoclave, but it messes up email addresses :-(

13:50 justin_smith: pbomb: the idea of a "temporary namespace" doesn't make much sense. Maybe you want a let block to bind things in?

13:50 (doc let)

13:50 clojurebot: "([bindings & body]); binding => binding-form init-expr Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein."

13:51 justin_smith: $grim let

13:51 err

13:51 $grim clojure.core/let

13:51 lazybot: http://grimoire.arrdem.com/1.6.0/clojure.core/let

13:51 justin_smith: see examples in the above link

13:51 pbomb: justin_smith: Doh, that simple - thanks.

13:53 justin_smith: pbomb: actually - so does the file have defn in it? if so it may need its own namespace

13:53 pbomb: justin_smith: Yes, it will have.

13:54 justin_smith: but in that case the right thing to use is the ns macro, creating an ns does not map clojure.core, but ns does that

13:54 or you could require that a migration define a namespace, unless it makes sense to put all the migration in one ns

13:55 puredanger: btw, I've been trying to track AOT issues at http://dev.clojure.org/display/design/AOT+Problem+Overview with an eye toward making a push to get them all fixed by 1.8. I may be missing some. please add it so.

13:58 Bronsa: puredanger: http://dev.clojure.org/jira/browse/CLJ-1495 is also a dupe of 979

13:59 puredanger: thx

14:00 Bronsa: puredanger: also CLJ-1544 is missing from that wiki page

14:00 err I mean 1457

14:00 puredanger: it's there?

14:00 oh, thx

14:01 Bronsa: sorry, I have a bunch of jira tickets open and I opened the wrong one

14:02 puredanger: CLJ-1457 does not seem overtly like AOT?

14:02 Bronsa: ah uhm you're right.

14:04 pbomb: justin_smith: Thanks.

14:04 justin_smith: Will explore all of the above.

14:05 Bronsa: puredanger: btw I'm scoping the patch for fixing the classloader issue rather than targetting only the AOT bugs. this just means that I'm replacing a bunch of class.forName calls with the patched RT.classForName

14:05 puredanger: sure

14:06 we will need to make the ticket align with the real problem/fix. I can help with that.

14:08 justin_smith: pbomb: also, you could manually call refer to get clojure.core into scope, you may want to consider clearing the ns when done as well (especially if there is more than one migration to run)

14:09 $grim clojure.core/refer

14:09 lazybot: http://grimoire.arrdem.com/1.6.0/clojure.core/refer

14:10 pbomb: justin_smith: I've just tried that and it seems to be working.

14:10 justin_smith: cool!

14:11 pbomb: the function for clearing the ns would be clojure.core/remove-ns

14:16 pbomb: justin_smith: Thanks, here's what I did in the end: https://programmers.stackexchange.com/questions/264601/i-would-like-to-run-load-file-in-a-sandboxed-namespace-in-clojure

14:17 justin_smith: pbomb: so you only need the keys from the loaded ns?

14:17 pbomb: justin_smith: No, eventually I'll need to execute a function from that ns.

14:18 justin_smith: aha, so then you probably want to export the whole ns-publics datastructure

14:18 since the remove-ns will unbind all of that

14:18 pbomb: justin_smith: I'll probably just pass in a body to be executed before remove-ns

14:18 justin_smith: but you can just use the map from ns-publics to find all the functions by name

14:18 aha

14:18 that works too

14:19 pbomb: Thanks again.

14:19 justin_smith: np

14:43 dimovich: Hello... I'm running Emacs on Windows with Cider 0.8.1 and cider-nrepl 0.8.1 (it's present in the maven cache)...

14:43 Nevertheless, I get "WARNING: CIDER's version (0.8.1) does not match cider-nrepl's version (not installed)"

14:44 maybe someone can point me to the right direction...

14:46 justin_smith: dimovich: how are you specifying to lein that the cider-nrepl lib should be used?

14:46 dimovich: usually you would add it as a dependency in ~/.lein/profiles.clj

14:47 dimovich: I have in my profiles.clj files the ":plugins [[cider/cider-nrepl "0.8.1"]"

14:47 justin_smith: it's not a plugin

14:47 it is used at runtime, so it has to be a dependency

14:47 so put it in :dependencies

14:47 gfredericks: unless it's a plugin that adds itself as a dependency

14:47 justin_smith: gfredericks: that's weird and bad and I hate that idea :P

14:47 gfredericks: which could make sense here since presumably you need to add middleware too

14:47 justin_smith: gfredericks: hmm

14:47 gfredericks: so only a plugin could do that in one step

14:48 I haven't checked if it actually does this or not :)

14:48 Bronsa: puredanger: would you rather a patch with 3 commit:, -fix RT.classForName, -replace Class.forName with RT.classForName -tests or a squashed patch?

14:49 justin_smith: gfredericks: anyway, I have never succeeded in using cider as a plugin, only as a dependency. I got it to work by switching it to dependencies rather than plugins

14:49 puredanger: Bronsa: squashed

14:52 dimovich: justin_smith: putting it in :dependecies breaks everything...

14:53 justin_smith: dimovich: that's really weird - what do you mean by breaks everything?

14:54 mavbozo: dimovich: i'm still using cider 0.7.0 and :plugins [[cider/cider-nrepl "0.7.0"]] in my windows maching

14:55 dimovich: mavbozo: thx

14:55 justin_smith: when I switch to :dependencies I get the "Please, install (or update) cider-nrepl 0.8.1 and restart CIDER"

14:57 Bronsa: puredanger: woop, race condition. I accidentaly removed your triaged

15:01 dimovich: Seems the warning appears whenever I start cider from a buffer in clojure-mode... If I start cider from a text buffer, everything runs ok...

15:01 Bronsa: llasram: cfleming http://dev.clojure.org/jira/browse/CLJ-979 vote up if interested

15:02 TylerE: What's the current recommendation for an intro book/tutorial that is up to date?

15:03 dbasch: TylerE: what’s your background?

15:03 TylerE: mostly python

15:03 some (common) lisp but that was like 10 years ago

15:03 dbasch: you can check this out and see if you like it http://www.braveclojure.com/

15:03 TylerE: so e.g. I don't need something that spends 100 pages talking about s-exprs and how cool macros are (but not how to write them)

15:04 mavbozo: dimovich: by starting, you mean cider-jack-in ?

15:04 dbasch: the joy of clojure is a great book if you’re already somewhat familiar with clojure/lisp

15:05 dimovich: mavbozo: yes

15:06 mavbozo: dimovich: maybe there's a conflict in your project.clj file? (assuming you are in a project dir)

15:08 TylerE: Clojure Programming contains some python codes as comparison

15:09 TylerE: even comparison of call syntax between Clojure, Java, Python, Ruby

15:09 in page 8

15:10 dimovich: mavbozo: yeah, the warning appears whenever I start cider from a project dir...

15:10 but project.clj doesn't define any :plugins

15:11 mavbozo: dimovich: try put cider-nrepl in :plugins

15:11 dimovich: in your project

15:13 dimovich: mavbozo: nope... same warning

15:13 I'll try making a new project with lein new, and see how that goes

15:16 mavbozo: the new project works fine... no warning...

15:18 puredanger: arrdem justin_smith andyf amalloy : fyi, chouser helped me out and I now have ops here

15:19 justin_smith: cool

15:19 amalloy: neato, thanks puredanger and chouser

15:19 Bronsa: nice

15:19 puredanger: the next time I chat with Rich, I'll ask him whether I can deputize a couple others

15:20 arrdem: sweet

15:20 sg2002: TylerE: Clojure programming is more or less current. Only some korma-related(clojure sql dsl) stuff changed.

15:23 TylerE: JOC is ok, but as someone who started with it, I won't really recommend it as your first clojure book. It's nice to read it later as kind of an exam of your clojure knowledge. Though maybe second edition changed... Haven't read that one.

15:24 chouser: We've heard reports that the 2nd ed is a bit easier to read, but JoC was never meant as an introductory book.

15:25 Bronsa: puredanger: so I have a version of the current patch that also fixes CLJ-1457

15:26 puredanger: I'll attach that version along the current one as this might need some discussion

15:26 puredanger: is it inter-related?

15:27 Bronsa: puredanger: kinda sorta. CLJ-1457 is fixed by making classForName _always_ look in the DynamicClassLoader cache first even if the baseLoader is not a DynamicClassLoader

15:28 puredanger: but this might just be a workaround, not sure.

15:28 sg2002: chouser: Well, you had some introductury stuff in it, so to me it looked like "you can use this as an introductury book, if you really wish". Still, thanks for the book, gonna also buy second edition when I'll have time to read it.

15:28 puredanger: Bronsa: does the 1457 change require the 979 change?

15:28 might be better to attach it to 1457

15:29 Bronsa: puredanger: yes it does

15:29 chouser: sg2002: yes, that's true. Maybe we would have been better out all suggestion of introductory material.

15:29 puredanger: Bronsa: well, attach it somewhere. :) I will take a look.

15:30 chouser: sg2002: Anyway, I hope you got some use out of the book.

15:32 sg2002: chouser: Was worth every penny. To bad that debug macro does not work well in cider. But I've read that there's gonna be a debugger in cider someday.

15:33 Bronsa: puredanger: attached & cross referenced

15:33 chouser: That's good to hear. You /can/ use a real debugger in emacs via ritz, but I'm uncertain if the value is worth the setup cost.

15:39 puredanger: amalloy: I gave you op, same as technomancy

15:42 xaxes`: hello, I've just started learning clojure and I have a little problem with stack overflow in this snippet: http://wklej.org/id/1548127/

15:42 what am I doing wrong?

15:42 EvanR: head explode once again, as it turns out java.util.Date is NOT zoned

15:43 puredanger: java.util.Date is the worstest

15:43 except for Calendar, that's worse

15:43 arohner: EvanR: use joda or jdk8 instants, if you can

15:43 EvanR: in the process i discovered the "next final form" of Calendar

15:43 pbomb: justin_smith: FYI, http://www.clodoc.org/doc/clojure.contrib.with-ns/with-temp-ns

15:43 justin_smith: Used to exist in contrib.

15:43 EvanR: arohner: yes, but i have to process java.util.Dates at least to get away from them

15:44 arohner: yup

15:44 justin_smith: pbomb: yeah, remarkably close to whate you ended up with

15:44 sdegutis: hello what is a good local backup strategy that doesnt use dropbox but has redundancy thank you

15:44 llasram: xaxes`: you seem to be swapping argument order in your recursive call

15:44 xaxes`: oh...

15:44 O

15:45 llasram: thank you

15:45 xemdetia: sdegutis, what are you even trying to back up

15:46 justin_smith: sdegutis: rsync

15:46 sdegutis: xemdetia: everything

15:46 justin_smith: thanks what kind of hardware thanks in advance

15:46 xemdetia: sdegutis, rsync is software and I would recommend just doing that

15:46 you need another server somewhere you are replicating to

15:46 justin_smith: sdegutis: rsync is a software, point it at a hard drive, and it does smart incremental backups, only sending things that have updated

15:47 xaxes`: llasram: now it throws null pointer exception ._.

15:47 sdegutis: i have a fireproof/waterproof backup drive i hope that will be enough

15:47 justin_smith: sdegutis: or you can even point it at a remote host, if the server is set up nicely

15:47 sdegutis: if you have the bandwidth for it, run rsync and point it to a machine in another location

15:47 sdegutis: justin_smith: thanks in advance, appreciated.

15:48 justin_smith: maybe populate the drive locally first, and then do the incrementals to a remote

15:49 sdegutis: I just found a bunch of crap I was working on in 2004 thanks to having used rsync. I thought it was lost but I had merely forgot where I put the external drive.

15:49 sdegutis: haha

15:50 justin_smith: like, I forgot how much ocaml code I wrote

15:50 sdegutis: i wonder does rsync handle nicely if you just move a directory to a subdirectory of another directory like does it know just to move things and not re-send everything thanks?

15:50 justin_smith: wow you must love ocaml

15:51 justin_smith: sdegutis: http://unix.stackexchange.com/questions/102620/rsync-that-handles-moves-sensibly

15:52 sdegutis: sick

15:52 justin_smith: http://rdiff-backup.nongnu.org/ looks nice actually

15:53 sdegutis: ill be the judge of that

15:55 crap i screwed up my dropbox sync somehow by moving two directories too quickly in a row and now its resyncing the whole thing

15:55 EvanR: put directory in directory

15:56 put bag in bag

15:57 epichero: put lime in coconut

15:57 mikerod: I'm fairly sure I read something about leiningen one time where you could work with 2 (or more perhaps) projects at the same time from the REPL in parallel

15:57 without any clean-install stuff

15:58 is this a plugin or a command? I am not seeing it come up in any searches, except one that had a dead link

15:58 justin_smith: mikerod: maybe lein checkouts?

15:58 https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies

15:59 mikerod: ok, I was searching for the wrong combinations of words I think

15:59 justin_smith: yes, that does ring a bell now. I think that's what I'm looking for. Thanks!

16:02 justin_smith: weird off topic question: what IRC channel would I ask about sending/receiving data via a serial port connected to a tandy102? Bonus points if I can get it hooked up as an actually tty I could log in to.

16:08 EvanR: ,#inst "2011-01-01"

16:08 clojurebot: #<SecurityException java.lang.SecurityException: denied>

16:13 justin_smith: &#inst "2011-01-01"

16:13 lazybot: ⇒ #inst "2011-01-01T00:00:00.000-00:00"

16:15 EvanR: &(.getYear #inst "2011-01-01")

16:15 lazybot: ⇒ 111

16:15 EvanR: &(.getFullYear #inst "2011-01-01")

16:15 lazybot: java.lang.IllegalArgumentException: No matching field found: getFullYear for class java.util.Date

16:17 dbasch: justin_smith: do you have a a computer with an rs232 serial port to connect to the tandy?

16:17 justin_smith: dbasch: rs232->usb adaptor

16:17 connected, but getting nothing but junk characters

16:17 dbasch: justin_smith: this thread from 1996 may be useful if you haven’t seen it https://groups.google.com/forum/#!topic/comp.sys.tandy/Ki7wu1shKwQ

16:18 justin_smith: I really like the idea of a simple laptop that runs on AA batteries, with a week of battery life, that can also be a terminal

16:18 dbasch: cool, thanks!

16:27 MartinHynar: hi, I am playing with an idea that component library could help me on controlling starting/stooping few things in my project, but I feel I am missing some clue on how to correctly use it when my functions need things controlled by component and I can't pass a component instance as parameter. So far, it is 1 day experience with component, so I might be perhaps not using it in the intended way, Hints welcome. I made an example here: https://gist.

16:30 geekygator: @MartinHynar I think your link got cut off

16:31 MartinHynar: https://gist.github.com/martinhynar/25abd9fb3e1ac88a9030

16:31 justin_smith: &(-> (doto (.build (java.util.Calendar$Builder.)) (.setTime #inst "2011-01-01")) (.get java.util.Calendar/YEAR)) ;; EvanR

16:31 lazybot: java.lang.ClassNotFoundException: java.util.Calendar$Builder

16:31 justin_smith: blerg

16:32 oh, Calendar$Builder is new in java 8

16:32 EvanR: the Date does not represent a date, but a timestamp. the Calendar does not represent dates either, but ZONED timestamps. WTF

16:32 MartinHynar: Are the links filtered out, or is it broken?

16:32 puredanger: MartinHynar: you might find this talk useful: https://www.youtube.com/watch?v=13cmHf_kt-Q

16:32 EvanR: youll have to excuse me i am new to java

16:33 justin_smith: EvanR: I think the preferred option is just to use joda time, which clj-time is a frontend for

16:34 EvanR: im using clj-time

16:34 puredanger: EvanR: unless you are on Java 8, where you should consider the new library (led by the joda author)

16:34 EvanR: and datomic gives you a Date

16:34 weavejes_: The Java date/time system is notoriously bad

16:34 EvanR: and my library accepts Dates and Calendars

16:34 weavejes_: puredanger: Oh, they're finally fixing it?

16:34 MartinHynar: puredanger: thanks, I'll see it first

16:34 puredanger: Java 8 has an entirely new library based on the ideas in Joda

16:35 JSR 310 was the project

16:35 TimMc: The weird thing is that it's not like they didn't put any thought into the old one.

16:35 I mean, just check out the javadoc for Date.

16:36 puredanger: http://www.threeten.org/

16:38 mikerod: I have a project that has both a Maven pom and a Leiningen project. It seems everytime I run `lein install` it overwrites my maven pom as well?

16:38 justin_smith: mikerod: lein install will replace anything you have locally with the same coordinates, yes

16:39 both the pom and the jar

16:41 kenrestivo: ~j.u.c.

16:41 clojurebot: Cool story bro.

16:41 kenrestivo: ~date

16:41 clojurebot: Cool story bro.

16:41 kenrestivo: ~j.u.d.

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

16:41 mikerod: justin_smith: can I stop this behavior?

16:42 justin_smith: why does it need to alter the pom? why not just package the project and install

16:42 I always just revert it :)

16:42 justin_smith: it generates and installs a pom

16:42 mikerod: hmm for some maven interop?

16:42 ordnungswidrig: mikerod: why shouldn't it update the pom?

16:43 justin_smith: there needs to be a pom file for the dep resolution stuff to work properly I think?

16:43 mikerod: ordnungswidrig: it is complicated, but I'm using leiningen only for development

16:43 kenrestivo: lein-pom?

16:43 justin_smith: mikerod: that's good, because lein is a development only tool

16:43 mikerod: we haven't been able to generate a sufficient pom via lein yet

16:43 so we have a manually made pom

16:43 that we use for deployment

16:43 ordnungswidrig: hmm

16:44 kenrestivo: could go the opposite way https://github.com/thickey/lein-nevam

16:45 mikerod: hah I did not notice why it was named taht until now

16:45 kenrestivo: i vaguely rememebr there being a lein plugin or set of project options that'd let you customize the generated pom

16:45 mikerod: I've seen some extensively complex poms generated via lein

16:45 I think it is possible now

16:45 justin_smith: mikerod: do you need to run lein install? what about lein jar, followed by using your known good pom and the resulting jar?

16:45 mikerod: but I have just not had a full-team onboard with that idea yet though

16:45 but lein is still great for development because there is a lot of support out there for it now

16:46 justin_smith: I'd imagine that would work

16:46 justin_smith: see also the pom options as demonstrated in the example project.clj https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L429

16:47 mikerod: one weird "issue" we currently have is we have "release scripts" that automatically go regex hunting maven poms to bump the version on internally developed snapshot dependencies

16:47 so if we were 100% based in the leiningen project world, it'd have ot find the dep versions to bump there instead

16:48 not impossible, just haven't went there yet

16:48 Beyond that, I think there is enough support now to generate some complex maven poms. I haven't seen how far it can be pushed though.

16:49 justin_smith: mikerod: in that example, it shows how to generate arbitrary xml output

16:49 mikerod: justin_smith: this example does have some good stuff init though, thanks for the link

16:50 justin_smith: I believe you are referring to :pom-additions

16:50 justin_smith: yeah

16:50 mikerod: I was not aware of that feature. That's pretty cool.

16:51 justin_smith: it's singular, though, no s

16:51 mikerod: woops, yes good catch hah

16:51 I'll have to play around with this and see how it works out

16:51 looks like lein is all-powerful now

16:53 sdegutis: I'm not sure we're creating the right macros. I think we'd do better to create lower-level macros e.g. language features or control-flow features, than to use them in APIs.

16:56 moquist: mikerod: I'm coming in late, but your comment about your "release scripts" tells me you might be interested in lein voom ( https://github.com/LonoCloud/lein-voom ) at some point.

17:02 andyf: sdegutis: whatever you use for local backups, I'd recommend keeping 2 physical backups, with one kept in different location (e.g. friend's home, safe deposit box, locked drawer at office) and rotate them every month or so. Protects against theft fire and some other things

17:02 mikerod: moquist: thanks for the link. this does look interesting. I'll have to look at it a bit more.

17:02 sdegutis: andyf: theft im not worried about (we live nowhere), fire what about just getting fireproof drive?

17:03 andyf: Yay, amalloy has ops. Kicks to spammers all around

17:03 kenrestivo: solo hoy :-)

17:04 * sdegutis ducks

17:04 andyf: sdegutis: Your call. Think how sad you might be if fire destroyed fireproof drive, and decide.

17:04 amalloy: goodness, do i? i guess i'll have to look up how to use this stuff

17:04 sdegutis: amalloy: do u also kickban trolls? just ciruous

17:04 amalloy: i will rule with an iron fist. anyone who doesn't say nice things about me at least once a day? gone

17:04 xemdetia: amalloy, u so pretty

17:05 andyf: (inc amalloy)

17:05 lazybot: ⇒ 201

17:05 EvanR: (dec amalloy)

17:05 lazybot: ⇒ 200

17:06 sdegutis: amalloy: my what large karma you have

17:07 puredanger: amalloy: use your powers only for good :)

17:07 hiredman: ~amalloy

17:07 clojurebot: amalloy is the spotlight illuminating my dumb mistakes

17:08 xemdetia: amalloy's karma can only be matched by his charity towards ducks

17:08 puredanger: amalloy: or for humorous mischief

17:08 amalloy: hah

17:09 sdegutis: $karma amalloy

17:09 lazybot: amalloy has karma 200.

17:10 xemdetia: is there a good place to read about the current state of binary logging in general? google is blown out for me by mysqlness

17:26 TimMc: andyf: I'd go further and recommend using a different backup strategy with each drive. Protects against certain systemic failures.

17:27 justin_smith: xemdetia: I think the "binary log" is a specific mysql thing, and not really a term for a general logging technique. Some systems store logs in a manner that is not human readable, but I don't think any of them distinguish that as their primary motive or feature.

17:27 andyf: Wow. I've been out-safeties

17:28 xemdetia: justin_smith, I was more talking just the general motions of the industry as a whole, e.g. systemd's binary logs and other fun stuff.

17:28 andyf: *safetied

17:28 TimMc: One of my backups is rsync with --link-dest to another drive (so a series of de-duped snapshots), another is tarsnap (remote, encrypted, de-duping), and a third is a drive image (done twice a year from a live USB.)

17:30 justin_smith: xemdetia: yeah, I don't think you can generalize about them though. Osx has binary logs, systemd has binary logs, mysql has binary logs. But other than the fact that humans can read them without some program that interprets the data, what else can we say about them as a group?

17:30 s/can/can't

17:31 ordnungswidrig: systemd binary logs are a clear deviation from the unix way of doing things.

17:32 fowlslegs: I'm trying to use flipBit for BigIntegers, but I can't figure out the java_interop syntax.

17:32 TimMc: ordnungswidrig: Would The Unix Way™ approve of structured (e.g. JSON) logs?

17:33 ordnungswidrig: TimMc: of course not :-) That kind of logs must be human readable

17:33 TimMc: JSON is pretty readable.

17:34 cfleming: Bronsa: I owe you beer, thanks :-)

17:34 gfredericks: it's a lot easier to go from JSON->readable than readable->JSON

17:35 TimMc: It has become increasingly clear to me that logs as a giant stream of random unstructured multiline crap is wrongheaded and only leads to pain.

17:35 EvanR: havent you heard of elastic search

17:35 TimMc: The fact that there are tons of log analyzers out there means we should be using structured formats in the first place.

17:36 Any time you have alerts based on graphs based on *regex analysis of human-readable debugging output* you've done something terribly wrong.

17:36 ordnungswidrig: TimMc: I'm all with you, as long as we're sure what will replace good old plain text. Every application inventing a binary log format is not helpful

17:36 I'd prefer edn :)

17:36 tuft: EDN works nice

17:37 TimMc: I'm not wild about binary formats in general.

17:37 * TimMc sticks his tongue out at SPDY

17:37 tuft: want to analyze some logs? open a repl

17:37 EvanR: make sure you dont log a :

17:38 edw: I'm looking for a no b.s. peer-to-peer messaging package for Clojure. Anyone really like anything in particular?

17:41 sg2002: ordnungswidrig: How about we replace good old plain text with clojure? ;-)

17:43 TimMc: We have metrics (which are great for primitive data) and audit logs (which are fine if you have a small number of schemas) and then we dump everything else to logs. I think that indicates we need something that's like a middle ground between all of those -- loose or no schema, amenable to graphing, data-bearing, non-lossy.

17:43 uris77: what does ${::some-symbol} do?

17:43 kind of hard to google for #{::}

17:43 Bronsa: ,::foo

17:43 uris77: sorry, s/$/#

17:43 clojurebot: :sandbox/foo

17:44 chouser: uris77: #{} is a set, and as Bronsa has shown double-colon reads as a keyword with a prefix equal to the current namespace

17:44 sg2002: uris77: It's a set with keyword ::foo

17:45 uris77: oh, so it just prepends the ns to the keyword inside the set

17:45 Bronsa: uris77: correct, and it also can resolve aliased namespaces

17:46 ,(alias 'foo 'clojure.core)

17:46 clojurebot: nil

17:46 Bronsa: ,::foo/bar

17:46 clojurebot: :clojure.core/bar

17:46 uris77: oh, nice

17:46 fowlslegs: ,(.flipBit (biginteger 8) 1)

17:46 uris77: thank you

17:46 clojurebot: 10

17:46 Bronsa: uris77: so if you have say (:require [some.ns :as s]), ::s/foo will resolve to :some.ns/foo

17:47 uris77: hmmm, can't I also just do s/foo without the :: prefix?

17:47 Bronsa: yes

17:47 ,:foo/bar

17:47 clojurebot: :foo/bar

17:47 Bronsa: ,::foo/bar

17:47 clojurebot: :clojure.core/bar

17:47 Bronsa: uris77: : will not resolve aliases in the keyword, :: will

17:47 TimMc: ,foo/bar

17:47 clojurebot: #<CompilerException java.lang.RuntimeException: No such var: foo/bar, compiling:(NO_SOURCE_PATH:0:0)>

17:49 TMA: ,'foo/bar

17:49 clojurebot: foo/bar

17:49 uris77: hmmm, I'm confused. I'm doing (:require [some.ns as s]) and s/foo works

17:49 s/as/:as

17:49 chouser: uris77: yes, but :s/foo is just :s/foo

17:49 TMA: ,foo/conj

17:49 clojurebot: #<core$conj__4079 clojure.core$conj__4079@32d521>

17:49 chouser: ::s/foo is :some.ns/foo

17:50 uris77: ah, ok

17:50 justin_smith: uris77: I think you are maybe unclear on the keyword vs. symbol distinction?

17:51 chouser: wow, what a lot of little details

17:51 s/foo only resolves to some.ns if some.ns has a var named foo

17:51 ...or if s/foo is in a syntax-quote

17:52 :s/foo never does

17:52 uris77: so, I understand that #{::foo} will give me #{:ns/foo} . I was just confused by (:require [some.ns :as s]), ::s/foo

17:52 chouser: rather, :s/foo is always :s/foo

17:52 and ::s/foo is :some.ns/foo regardless of the existence of any var in some.ns

17:52 Bronsa: chouser well yeah I mean, symbols always resolve to vars or error out, keywords have nothing to do with vars

17:52 uris77: my confusion was that I can also do s/foo and couldn't understand why I would need ::s/foo

17:54 but I think I understand now. if I need to add a function from that ns into a set, I can do so using :: . Sorry for being confused. Newbie here.

17:54 Bronsa: chouser keywords don't really have much to do with namespaces either it only happens that they resolve alias using a shared mapping with the namespace system

17:55 chouser: Bronsa: you're right. Add something about syntax-quote and we'll have said much the same thing. :-)

17:55 Bronsa: uris77: no, you are confusing keywords with symbols. symbols have no ':' and map to a value, keywords have a : and _are_ values

17:55 TMA: ,(namespace ::foo/bar)

17:55 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: ::foo/bar>

17:55 Bronsa: TMA the alias expired

17:55 ,(alias 'foo 'clojure.core)

17:55 clojurebot: nil

17:55 TMA: oh

17:55 Bronsa: ,(namespace ::foo/bar)

17:55 clojurebot: "clojure.core"

17:56 TMA: ,(namespace :clojure.core/bar)

17:56 clojurebot: "clojure.core"

17:56 TMA: ,(namespace :foo/bar)

17:56 clojurebot: "foo"

17:57 TimMc: Bronsa: Well... symbols also *are* values, but it is not their primary function.

17:57 Bronsa: TimMc: in the context of evaluated clojure only *quoted* symbols are values

17:58 justin_smith: uris77: and the point of namespaced keywords is when you have a map that could contain vailues from multiple places, it prevents the keys different libs use from colliding

17:58 TimMc: Mmm, fair.

17:58 justin_smith: *values

17:59 TimMc: Bronsa: Clojure has so much support for self-evaluating literals that lists and symbols are kind of an exception -- and I forget about them when talking about code-as-data. :-)

17:59 whereas in some other lisps self-evaluating forms are more of a novelty :-P

17:59 chouser: Is that a condescention of programmers? No, it's a pedant of Clojurites! ;-)

17:59 Bronsa: TimMc: it doesn't help much that the difference between the different stages are not that clear cut. Makes it hard to talk precisely about this stuff

18:00 TMA: TimMc: I do not concur. symbols and list are the only non-self evaluating objects in Common Lisp

18:01 TimMc: TMA: How many self-evaluating forms does Common Lisp have? I'm not familiar with it.

18:01 * Bronsa is too tired to understand what evaluates what

18:01 TMA: TimMc: take the numerical constants for example. 1 => 1

18:02 TimMc: Numbers are probably universally in that category, yes. :-)

18:02 (def 3 (+ 2 1))

18:03 justin_smith: TimMc: yeah, likely the only languages without numeric literals are the super-minimal esolangs

18:03 TMA: TimMc: or the strings "a" => "a" ; vectors #(a b c) => #(a b c) ; structures (as defined by defstruct)

18:03 Bronsa: andyf: ping

18:03 andyf: Pong

18:03 TimMc: Strings!

18:03 But not everyone has vectors and sets and maps as literals.

18:03 Bronsa: andyf: next t.a.jvm snapshot is going to break a lot of your pattern matchings against ASTs

18:04 TimMc: Booleans and nil vary as well.

18:04 I think in Racket, true, false, and nil are symbols that eval to those values.

18:04 I really appreciate that regularity.

18:04 justin_smith: keywords, characters, regexes

18:04 TMA: alas CL has no standard notation for sets/maps

18:04 justin_smith: dates

18:05 record types

18:05 Bronsa: andyf: just warning you in case you wanted to try it. I'm thinking about adding a function to safely pattern match (:do/:with-meta aware)

18:05 andyf: Thanks for advanced notice. I'll be sure not to update to latest t.a.j. until I'm ready to go through that.

18:07 I can always destress myself by remembering: "Eastwood is only a lint tool, with no computational results that are affected if output is undesirable." :-)

18:07 TMA: TimMc: but, all-told, when writing an evaluator for CL you have (defun eval (v ...) (cond ((symbolp v) (eval-symbol v ...)) ((consp v) (eval-list v ...)) (t v)))

18:10 Bronsa: andyf: ah I cut a release with the column patch a few hours ago. Many thanks for the help on that

18:10 andyf: a tools.reader release, that is

18:11 andyf: Grazie. Latest code I've been checking in doesn't rely on that, but I probably will some day

18:39 turbofail: g

18:39 whoops

18:47 m3talsmith: bbyler_tho: hi

18:48 bbyler_tho: m3talsmith hey buddy!

19:04 arohner: I don't suppose anyone has a library that works like deliver, but throws exceptions when deref'd?

19:05 I'd like to be able to (let [p (promise)] (deliver p (/ 1 0)), and have deliver store the exception, and make @p throw it

19:10 hiredman: arohner: manifold maybe

19:11 I haven't used it, but if I recall it has a thing like a promise with the concept of failure and success

19:11 arohner: hiredman: that looks interesting, thanks

20:20 david234567: Hello! I have a question about core.async channels. If I have a channel with a buffer size of 10 and I put 10 things into it, then read 10 things into it, can I then put more things into it?

20:22 thearthur: david234567: yes

20:22 if you ment read 10 thuings out of it

20:22 rather than "then read 10 │ Cr8 things into it

20:23 (cut pase failZ)

20:25 david234567: I did mean that, read 10 things out of (<!)

20:25 *of it

20:25 ook, awesome. Thank you!

20:26 (I was worried for a bit there)

20:28 doritostains: I have a function that returns a multi-artiy function, how do I call one of the arities from the other?

20:32 hyPiRion: ,((fn foo ([a] (foo a 1)) ([a b] (+ a b))) 2)

20:32 clojurebot: 3

20:36 david234567: Another question about async, when does >!! stop blocking?

20:37 doritostains: hyPiRion: thanks! didn’t know fn could take a name!

20:42 thearthur: david234567: when a message is recieved or the channel is closed

20:43 iff the channel is closed will it return nil

20:44 david234567: sorrh read that the other way, when a message is read from the channel or someone else closes the channel

20:44 david234567: ook, Thank you thearthur!

20:54 kenrestivo: unless you have a buffer...

20:55 if it's a sliding buffer it'll never block at all.

20:55 or dropping buffer

20:59 david234567: When I open a clojure file in emacs/cider that depends on other files in the same directory, why do I get a compiler error (classpath) error when I try to load it into the repl?

21:00 I guess it's expecting the other files to be opened first

21:00 but it should be able to find them right?

21:00 gfredericks: are those files actually on your jvm's classpath?

21:01 it's funny you ask this because I just got done manually evaling like six files because they were in a different project

21:01 david234567: I actually don't know how to do that

21:02 itruslove: david234567: something else that springs to mind is if that you have dashes in your namespace names, they should be underscores in the file path

21:02 gfredericks: david234567: typically you will organize your code as a leiningen project; when you have that, doing M-x cider-jack-in from one of that project's files should do the right thing

21:02 `lein new foo` to generate a project

21:03 david234567: ook, here's a picture of my problem

21:03 http://i.imgur.com/3zQBfkC.png

21:04 I used cider-jack-in on serverlist.clj and C-c C-k'd it

21:04 I then opened profiles.clj

21:04 gfredericks: david234567: there's just one project involved here?

21:04 david234567: yeah

21:05 erm

21:05 I guess so, I had to wrangle async_sockets to work right by downloading the file and placing it with the rest

21:06 Here's the part of code that it doesn't like

21:06 http://i.imgur.com/1kzaYrc.png

21:09 not sure if this helps but this is the dir structure

21:09 http://i.imgur.com/vVa1HuB.png

21:09 itruslove: david234567: have you restarted the repl since adding the dependency on com.gearswithingears/async-sockets in your project.clj?

21:10 david234567: yes, but I could probably remove that as it doesn't work (i'm not sure why)

21:14 now it can't find core.async hmm

21:14 itruslove: david234567: I think the problem is what you're requiring

21:15 you need to (:require [com.gearswithingears.async-sockets :as s])

21:15 I was looking at https://github.com/bguthrie/async-sockets/tree/master - I think the README is wrong

21:16 you should only need the source files you are writing in your src directory - the rest should be deleted.

21:17 Check out the tests - https://github.com/bguthrie/async-sockets/blob/master/test/com/gearswithingears/async_sockets_test.clj#L6

21:19 david234567: Ok! I'll try that

21:20 :O IT WORKS!

21:20 :D

21:21 itruslove: great!

21:21 david234567: Thank you so much!

21:21 itruslove: you're very welcome. Good luck with the rest!

21:27 david234567: Thank you to everyone here! I'mma go now, thanks again!

21:52 craigglennie: I’m using Cursive Clojure, and wondering if there’s a way to do partial history completion / partial history search (I don’t know the correct term) when using the REPL. For example, in iPython, if I type “def get” and press up it only shows history where the text started with “def get”

21:52 I think Cursive is using nREPL, and I tried to find a setting for that option, but I think maybe it doesn’t exist

21:53 cfleming: craigglennie: You're looking for the Tools->REPL->Search REPL history action

21:53 craigglennie: Which you can bind to a key, of course

21:53 craigglennie: You can invoke that from anywhere, too - you don't have to be in the REPL editor

21:54 craigglennie: cfleming: It doesn’t seem like I can type part of what I want to find, but this is still much better

21:54 cfleming: craigglennie: Yes, you can type in that popup and it will narrow down

21:56 craigglennie: clfeming: I see… it’s a little counter-intuitive; I thought I could type in the lower window that shows the text of the selected command, but I can’t. When I tried to select the top window to see I could type in there I found that any click selects the command under the mouse, closes the window, and puts the command in the REPL

21:56 cfleming: So the typing only works if it’s the first thing you do after the search window is opened, I think

21:56 cfleming: But that’ll work

21:57 cfleming: craigglennie: What else might you have done after the window is opened?

21:57 craigglennie: Click on an element or something?

21:57 craigglennie: Well the bottom half of the window looks like a text input field

21:57 So I clicked on it

21:58 cfleming: And then I can no longer search by typing - key strokes do nothing

21:58 cfleming: craigglennie: I see, you're right - that does seem to be broken.

21:58 craigglennie: cfleming: So I need to close that search and re-open it

21:58 cfleming: craigglennie: Thanks, I'll fix that.

21:58 craigglennie: cfleming: Awesome, thanks for the help

21:59 cfleming: Also, I really like Cursive

22:00 cfleming: craigglennie: No worries - I filed this so I don't forget about it: https://github.com/cursiveclojure/cursive/issues/664

22:00 craigglennie: Thanks, glad you're enjoying it!

22:02 nullptr: (inc cfleming)

22:02 lazybot: ⇒ 5

22:05 akkad: joy of clojure has arrived :P

22:12 jay449: clojure noob here. i am wring my first web app in it using compojure, etc. lotsa fun. however, one big problem: my upload bandwidth is not too good. and "lein ring uberjar" makes a roughly 40mb jar. is there a way to produce a smaller bundle when i make a small change? uploading 40mb jars to a real test server gets too much. current best solution: build from code on test server. haven't implemented that yet... was wo

22:12 ndering if there is a better solution.

22:25 fairuz: When developing I think you don't need each time to generate a jar

22:25 I use liberator + compojure + ring, and just doing (go) in the repl will start my web server. Any modification after that, I just need to do (reset)

22:34 jay449: fairuz: thanks

22:34 i use the repl too for local testing

22:34 however, i still deploy 4-5 times a day to the real server to do some manual testing

22:35 each deploy takes me like 3+ minutes on my connection

22:37 jswanson_: jay449: i would just install lein on the server

22:37 felixflores: hi all :)

22:37 jay449: haha, ok, that seems like what i was thinking

22:47 sm0ke: ,(with-out-str (print "123"))

22:47 clojurebot: "123"

22:47 sm0ke: ,(with-out-str (.print System/out "123"))

22:47 clojurebot: ""

22:48 sm0ke: any way to capture a System.out.println to a string?

22:53 i thought print just wraps System.out.print

22:54 but it does not seems to be true

22:54 gfredericks: sm0ke: I think technically you can redefine System/out

22:55 sm0ke: gfredericks: yes but i want to call a external api fucntion which prints uing System.out

22:56 gfredericks: so if you redefine it...you might be able to capture it?

22:56 not sure what I'm missing

22:56 sm0ke: ,(macroexpand-1 (with-out-str (.print System/out "123")))

22:56 clojurebot: ""

22:57 gfredericks: with-out-str uses *out*

22:57 sm0ke: ,(macroexpand-1 '(with-out-str (.print System/out "123")))

22:57 clojurebot: (clojure.core/let [s__4979__auto__ (new java.io.StringWriter)] (clojure.core/binding [clojure.core/*out* s__4979__auto__] (.print System/out "123") (clojure.core/str s__4979__auto__)))

22:57 sm0ke: is ##clojure.core/*out* ; not System/out

22:58 gfredericks: I know

22:58 I'm suggesting changing System/out itself

22:59 (.setOut System ...)

22:59 sm0ke: gfredericks: wouldnt that be a global setting?

22:59 gfredericks: yes; this is the best you can do

22:59 afaik

22:59 sm0ke: weird

22:59 gfredericks: ~java

22:59 clojurebot:

23:00 sm0ke: too hot to handle

23:00 gfredericks: ~java

23:00 clojurebot: java is a mutable basket case

23:01 gfredericks: ~java

23:01 clojurebot: java is a mutable basket case

23:01 echo-area: Why is it responding differently

23:01 ~java

23:01 clojurebot:

23:01 echo-area: ~java

23:01 clojurebot: java is a mutable basket case

23:01 sm0ke: clojurebot: java *is* nuts

23:01 clojurebot: excusez-moi

23:01 sm0ke: clojurebot: java |is| nuts

23:01 clojurebot: Ack. Ack.

23:01 sm0ke: ~java

23:01 echo-area: Everyone only gets one chance, and I have used it up :'(

23:01 clojurebot: java is a mutable basket case

23:02 sm0ke: ~java

23:02 clojurebot: java is nuts

23:02 echo-area: ~java

23:02 clojurebot:

23:02 echo-area: Hah, it's back

23:02 Jaood: ~scala

23:02 clojurebot: scala is a good way to make people hate functional programming

23:02 Jaood: ~haskell

23:02 clojurebot: "you have to see features like that in the context of Haskell's community, which is something like Perl's community in the garden of Eden: detached from all shame or need to do any work." -- ayrnieu

23:03 echo-area: ~common lisp

23:03 clojurebot: common lisp is howl's moving castle

23:03 Jaood: ~javascript

23:03 clojurebot: javascript is beautiful, you're just too conformist to appreciate its quirks: http://tinyurl.com/7j3k86p

23:03 michel_slm: ~haskell

23:03 clojurebot: haskell is Yo dawg, I heard you like Haskell, so I put a lazy thunk inside a lazy thunk so you don't have to compute while you don't compute.

23:04 michel_slm: ~elixir

23:04 clojurebot: Gabh mo leithscéal?

23:04 michel_slm: ~elixir

23:04 clojurebot: It's greek to me.

23:04 michel_slm: ~erlang

23:04 clojurebot: http://www.unlimitednovelty.com/2011/07/trouble-with-erlang-or-erlang-is-ghetto.html

23:04 michel_slm: someone needs to teach clojurebot some new languages ;)

23:04 ~lua

23:04 clojurebot: Huh?

23:05 michel_slm: ~swift

23:05 clojurebot: excusez-moi

23:05 sm0ke: clojurebot: scala |is| object oriented, imperative, functional, and twenty other thing you can think of

23:05 clojurebot: c'est bon!

23:05 michel_slm: ~scheme

23:05 clojurebot: scheme is Scheme is like a ball of snow. You can add any amount of snow to it and it still looks like snow. Moreover, snow is cleaner than mud.

23:05 michel_slm: ~ocaml

23:05 clojurebot: Pardon?

23:05 Jaood: ~emacs

23:05 clojurebot: emacs is a nice operating system if it only had a decent editor

23:05 michel_slm: ~ml

23:05 clojurebot: Excuse me?

23:05 michel_slm: ~vi

23:06 Jaood: ~clojure

23:06 clojurebot: clojure is for robots

23:06 michel_slm: ~clojurescript

23:07 hmm, seems like I'm rate-limited

23:07 Jaood: ~taco bell

23:07 clojurebot: Pardon?

23:12 dkoontz: is anyone here familar with how to use Clojure interop to run a static Java method and then launch that using lein run, I keep getting errors like "Exception in thread "main" java.lang.NoSuchFieldException: main" when I try to do something like (MyJavaClass/main) from my clojure -main function

23:14 sm0ke: (MyJavaClass/main (into-array String []))

23:14 ^^ dkoontz

23:15 dkoontz: interesting, does Clojure fail to find main because it's looking for a main that takes 0 args?

23:15 sm0ke: yep

23:16 arrdem: well... Java would fail if you made that same method invocation so why should we work?

23:16 adding implicit empty sequences would be... weird

23:16 sm0ke: totally

23:16 arrdem: adding implicit nils would be friggin evil

23:16 sm0ke: but its weird to write (MyJavaClass/main (into-array String [])) this as well

23:17 dkoontz: hrm, I was thinking args was a params in Java

23:17 I guess it's not

23:17 been too long in C# haha

23:17 sm0ke: i would ideally love a cleaner syntax for Java's ... args calling from clojure

23:17 arrdem: (->> [] (into-array String) MyJavaClass/main)

23:17 dkoontz: yeah it makes sense to not resolve without the array

23:17 arrdem: &(class (into-array String []))

23:17 lazybot: ⇒ [Ljava.lang.String;

23:18 dkoontz: lazybot: I did try type hinting with that exact type and passing a vector, that didn't work

23:18 arrdem: &(instance? (class (into-array String [])) nil)

23:18 lazybot: ⇒ false

23:18 arrdem: damnit

23:18 sm0ke: arrdem: do you know if there is an additional copilation artifact to Java's func(Object... objs) ?

23:19 arrdem: sm0ke: not offhand

23:19 sm0ke: if yes clojure could turn them into varargs?

23:19 like [& objs]

23:20 arrdem: I would need to look at some JVM bytecode and think about that for a while

23:20 IIRC Object... objs is passed as Ljava.lang.Object

23:20 as are Clojure Varargs

23:20 so... maybe?

23:20 but not "trivially" that I can imagine.

23:21 thoughts on adding hosted articles to Grimoire 0.4 or should I just be linking out to clojure-docs as an article store?

23:30 sm0ke: i think i should use grimoire more. looks great

23:31 arrdem: eh it's actually kinda broken ATM because I'm changing the way I store data

23:32 all the edit links are fucked

23:32 hopefully over Christmas I'll be able to get it up to the ClojureDocs living document standard

23:32 sm0ke: arrdem: whats with the 3000 port?

23:33 gfredericks: (* 2 2 2 3 5 5 5)

23:33 clojurebot: *suffusion of yellow*

23:33 gfredericks: ,(* 2 2 2 3 5 5 5)

23:33 clojurebot: 3000

23:33 arrdem: sm0ke: hum? oh why is the real server on 3000? because I originally ran Grim on the same server as my blog, so both ran on not 80 and nginx dealt with it

23:34 sm0ke: when Grim moved to its own server I just kept 3000 because I'm a lazy bugger

23:47 dkoontz: ok, another probably dumb question, I have an app I can run with lein run that uses local jars that I include using :resource-paths in my project.clj. When I lein uberjar, the manifest doesn't include those jar files. Is there a config option to cause that to happen?

23:51 sm0ke: dkoontz: you can install them locally into your maven repo and add them as normal deps

23:52 http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

Logging service provided by n01se.net