#clojure log - May 23 2014

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

0:08 beamso: gen-class didn't show me anything to suggest that it would

0:08 http://stackoverflow.com/questions/11783736/how-can-a-static-initializer-be-defined-using-gen-class may or may not be a help

0:11 rritoch: beamso: Thanks, I actually ran into that and the clinit method mentioned seems to hint at a possible way but I don't think relying on undocumented features will be the best way to go.

0:14 yeoj___: hi, i'm reading a few web development books and focusing on selmer right now... does anyone know if it's supposed to pick up a set session with varibales by default in a template? Or do i have to constantly pass the session/get results back into the template?

0:16 i can't seem to access session/flashset! data either... strange. i can see it as set in the browser log.

0:21 rritoch: beamso: Ultimatly the core of the issue comes down to needing to load native dependencies using the appropriate class loader, static initializers seem to be the only thing that works properly. I'll try a different direction then. I may be able to cache the appropriate classloader from a static constructor for later use in calls to load the native dependencies. It sounds good, just not sure if it will work.

0:22 beamso: there is nothing wrong with that code simply being in java

0:23 you could even try having that static initialization in a java class and using gen-class to extend that class

0:24 rritoch: beamso: In this case there actually is. The build system for the WarpCTL extra libraries (NVML + ADL-SDK support) can't be made fully automatic since after the swig code is generated the static initializers need to be added which breaks the automation.

0:25 As for extending via gen-class I considered that but I don't think there is any way to have the static initializer call a method in a deriving class without knowing its name beforehand.

0:27 beamso: the code generation isn't separated into interface/implementation?

0:28 rritoch: beamso: I don't think there is any such thing as a static interface, at least not that I'm familiar with.

0:29 That gen-class idea though does leave open some bold ideas though

0:29 beamso: with java 8 you can have static methods on interfaces

0:30 i was thinking more of soap interop where you take the schema, let the client and server code be generated and you add your code around that

0:32 egghead: do you think that edn is accessible to the larger programming community?

0:32 beamso: not as accessible as JSON.

0:34 rritoch: Just thinking maybe I can throw an exception and use the history to figure out the name of the class being loaded, but that is a bit of a stretch

0:35 I also haven't used java 8 yet

0:35 beamso: i've only used the streams part so far

0:36 having code that breaks when generation breaks isn't unheard of or necessarily a problem

0:39 rritoch: well, right now I'm targeting java 6 because that seems to be the lowest version that most people have (assuming they have auto-updates enabled). Originally my static constructor was a case statement matching strings (Java 7) until I realized that it didn't work on some of my machines.

0:40 beamso: java 6 is eol unless you're paying oracle for support.

0:41 java 7 will be eol in just under a year : http://www.oracle.com/technetwork/java/eol-135779.html

0:43 rritoch: Well, my linux debian (Jessie) which is only in testing and not yet released only had java 6 support out-of-the-box, since then I've installed some JDK's but even if it is eol there will still be a lot of people using it. Java 6 seems to run fine on Java 7, but I haven't yet tried it on Java 8 so I will soon find out.

0:45 beamso: the most recent version of sun java on debian etc. is version 6 as oracle removed the ability for linux distros to repackage java releases for distros.

0:45 rritoch: Either way, the WarpCTL project is going to take years to get to a first release so I can push right up to any version that's released since by the time my release is ready v8 will probably be el.

0:45 beamso: i thought that most distros had moved to openjdk while allowing the user the ability to download java packages from oracle and allowing them to configure update-alternatives etc. to point to their chosen java release.

0:48 Jaood: rritoch: are you sure you are running debian?

0:48 rritoch: My debian machine is a mess. It has a 4th generation motherboard and 2 AMD R9's crossfired so I can only get it to function with the latest kernals which means I'm stuck with unstable versions of debian. Needless to say java configuration wasn't high on my todo list since I can't even get the machine stable. It is working today but a week from now I'll probably be back to doing repairs.

0:49 Jaood: debian stable (wheezy) has a packave for java 7

0:49 rritoch: Jaood, I'm not on wheezy, since wheezy doesn't support my "Killer" ethernet card.

0:50 Jaood: rritoch: my point was that wheezy is older than jessie

0:51 so if wheezy already ship with openjdk-7-jdk, why are you using openjdk-6 in jessie?

0:51 rritoch: Jaood, I see your point, When jessie finally does release it probably will have java 7c

0:52 I honestly don't know, It looks like I have 6 and 7 installed (of openjdk)

0:52 beamso: it looks like openjdk versions 6 and 7 are separate packages

0:52 rritoch: I'm not sure why it defaults to version 6

0:52 benkay: i have a compojure route with /stuff/:thing, and I'm looking to capture both the request and :thing, but (GET "/stuff/:thing" [request thing]) is (unsurprisingly...) not doing what I expect as apparently the request is not bound. does anyone have any insight into what I'm missing here?

0:52 Jaood: you can just remove openjdk-6 if you don't want it

0:55 benkay: ah, I'm looking for the :as symbol.

0:55 rritoch: Jaood, to be completely honest I'm not touching a thing until it breaks again. This machine is a mess, if I look at it the wrong way it will crash. They release new kernels every few weeks and each new kernel seems to be incompatible with the catalyst driver so there is simply no way to make this machine stable (yet).

0:56 It is my stress-test machine since it has the most computing power, but other than that its useless.

0:57 Jaood: rritoch: you should run an ubuntu stable release instead of using debian testing then

0:59 quizdr: man getting a browser repl going is not so easy on the first try

0:59 rritoch: Jaood, you are probably right. I haven't tried ubuntu, I just recently switched from Centos to Debian because of the missing encryption algorithms in Centos.

0:59 Ubuntu seems to have more hardware support, but debian seems to have more software support, so it seems to be a trade-off at this point.

1:01 Anyhow, sorry for letting this go so far off topic. My next step will be to try to cache the class loader used by static initializers in Clojure, that may completely eliminate m need for static initializers.

1:10 beamso: Your suggestion to extend a class with a static class loader will probably fit into this approach perfectly. Thinking about the situation if I extend the class which caches the appropriate class loader than that guarantees the availability of the cached class loader for me to call the native loading from.

1:13 beamso: i would test it. i have no idea if it will work from clojure.

1:14 rritoch: beamso: Neither do I. The only remaining problem will be to ensure the native dependency is loaded before it's needed but that can typically be dealt with using reflection.

1:15 beamso: the static nature of the code block you previously showed me means that the loading of the resource happens when the class is referenced by code in the JVM during runtime.

1:19 rritoch: beamso: Yeah, and that includes during the compile stage. The NVML wrapper generated by swig creates static properties that are derived from native code so for that I had to use a lot of reflection to ensure it would still compile for machines that didn't have NVML support.

1:23 The only way I'm going to know is to try it but if I can eliminate these static initializers than I can fully automate the build system which would be a big step forward for cross-platform compatibility.

1:32 quizdr: I have this dependency yet at the repl for my project i can't refer core.async [org.clojure/core.async "0.1.303.0-886421-alpha"] It says no namespace found for (refer 'clojure.core.async) or (refer 'core.async) any thoughts?

1:34 arrdem: you need to use require not refer

1:35 quizdr: ah, thanks!

1:45 kelseygi: i’m looking at this code and trying to figure out the benefit of sending code that delivers a promise to an agent bteoh

1:45 er

1:45 https://github.com/mccraigmccraig/twitter-streaming-client/blob/master/src/twitter_streaming_client/core.clj#L35-L49

1:45 the deref on line 49 will block until delivery, right?

1:45 so what does sending off the deliver function get you there?

1:48 uh mccraig i think that’s your code :)

1:49 beamso: in the other file in the namespace, that inline function is called

1:49 not namespace, package.

1:52 kelseygi: right, i get that, beamso, but why wrap it in a promise

1:52 oh because the agent call just returns the agent itself?

1:52 quizdr: here's a short question regarding a basic core.async example if anyone is smart enough to explain it: https://www.refheap.com/85823

1:52 kelseygi: ok i think i get it now!

2:37 ddellacosta: quizdr: this describes it in Java but the essence is the same from skimming the JS code: http://hueypetersen.com/posts/2013/08/02/the-state-machines-of-core-async/

2:40 quizdr: ddellacosta hadn't seen that link before, thanks. this "non-blocking" aspect of these go blocks in JS is interesting to me. that they are just "watching" and "waiting" for results to come in, while on the same thread as your other logic

2:42 ddellacosta: quizdr: yeah, it seems like in the JS version at least, it's a state machine getting updated based on setTimeout (or js/MessageChannel / js/setImmediate): https://github.com/clojure/core.async/blob/master/src/main/clojure/cljs/core/async/impl/dispatch.cljs#L41-L43

2:47 myguidingstar: hi all, I remember an article states that core.logic can be used to give better performance than Neo4J. Anyone knows where I can find the article again?

2:51 quizdr: ddellacosta you ever use this goog.dom convenience ".innerHTML" ? I'm trying to an cljs compiler claims that function doesn't exist. additionally, it's not on the API: http://docs.closure-library.googlecode.com/git-history/15160ce901b70ac9df5e7d25ae4835835738f782/closure_goog_dom_dom.js.html

2:51 yet i see it in a dnolen tutorial

2:52 ddellacosta: quizdr: you may have to include goog.dom explicitly; how is he including it?

2:52 requiring/importing rather

2:53 quizdr: (:require [goog.dom :as dom])

2:56 ddellacosta: quizdr: dunno, sorry...but you could just skip it and do (set! (.-innerHTML) ...) i suppose

2:56 quizdr: i wonder why sometimes i can compile a cljs file and it compiles quickly and successfully, even though it complained before. if i make a trivial change like adding a blank line and compile again, then all the errors that were there previously return

2:56 ddellacosta: quizdr: is it the same file?

2:56 quizdr: yes

2:57 ddellacosta: dunno, never seen that

2:59 quizdr: i shall pour into that state machine article now, see if i can absorb the truths by sheer quantity of varied explanations

3:01 ddellacosta: quizdr: I recommend taking a look at the source while you're at it; it's really not that hard to follow especially with that article to help

3:04 quizdr: ok

3:04 i shall try

3:04 you mean the java source or the cljs source?

3:08 ddellacosta: oh, either

3:08 whichever one suits your fancy. :-)

3:08 or both

3:09 quizdr: i wonder if i'm one of the few clojure enthusiasts who has never written a line of Java

3:09 i also wonder if it will stay that way

3:15 ddellacosta: quizdr: many Clojure folks came to it without much or any Java experience

3:16 on that note, I wonder if anyone here knows how to get ahold of this jar for inclusion in a Clojure project... javax.activation.MimetypesFileTypeMap

3:16 or is it available by default? hmm

3:18 huh, guess so

3:48 trap_exit: clojure

3:48 is there a way to do stateful macros?

3:48 I would like to define macros foo & bar so that

3:49 (foo 20) (bar) ==> results in (bar) expanding to 20

3:49 but I want this to ahppen during compile time

3:53 ambrosebs: trap_exit: use a top level atom and reset it inside the defmacro body

3:53 trap_exit: trying that now

3:53 ambrosebs: thanks

3:53 wait

3:53 is ambrosebs a good mallard duck of a evil mallard duck ?

3:54 ambrosebs: trap_exit: I worked that out while trying to implement a feature for core.match

3:54 unsure if it was worth it ;P

3:54 trap_exit: ambrosebs: oh, instead of using core.typed

3:54 I have my own defn-safe

3:54 so wheneer I define a function, I want to record meta information about it

3:54 this is going to be fun

3:55 for certain values of fun

3:55 ambrosebs: trap_exit: for compile-time validation?

3:55 trap_exit: yes :-)

3:55 ambrosebs: nice

3:55 trap_exit: run time is too fucking slow

3:55 it causes 45% of the time in chrome

3:55 to be spent in gc

3:55 ambrosebs: ok

3:56 trap_exit: basically, I was passing arguments as maps {:arg1 ... :arg2 .... }

3:56 now I need to do macros to "unmapify" the args at compile time to avoid creating maps all over teh place

3:56 ambrosebs: right

3:57 trap_exit: there is one ugliness

3:57 perhap[s you can tell me a trick to solve this

3:57 previously, I did (defn-safe func-name .... ) (func-name {:foo ... :bar ... })

3:57 now, I will be doing (defn-safe func-name ... ) (call func-name {:foo ... :bar ... })

3:57 where "call" is a macro that de-mapifies stuff

3:57 is there a way to get rid of the "call" ?

3:57 I suspect no. But you seem to be into the dark arts of clojure macros.

3:58 ambrosebs: I think you can do something like that with the cljx stuff that cemerick's made

3:58 trap_exit: suppose I could how can the run time know between where to stick a "call" or not?

3:59 i.e. how does it satisfy (my-fucked-up-func ... map) vs (clojure-builtin .... )

3:59 ambrosebs: trap_exit: you'd have to use tools.analyzer to pull apart your code

3:59 trap_exit: I did not consider that.

3:59 That sounds trivial to debug.

3:59 ambrosebs: trap_exit: but the trick is inserting tools.analyzer in the evaluation process.

4:00 which is where the cljx stuff comes in I think

4:00 trap_exit: we should kidnap cemerick and lock him in a basemene tuntil he writes a tutorial on design + implementation of cljx

4:00 I really wish clojure tools were better documented. :-)

4:00 ambrosebs: I think this is the video I'm thinking of https://www.youtube.com/watch?v=Ah9p8cqkTOg

4:01 trap_exit: meh, everything is pretty young

4:01 trap_exit: we can call off the kidnapping

4:01 ambrosebs: I'll change

4:01 trap_exit: I will watch the video instead

4:01 ambrosebs: :)

4:01 It'll

4:01 haha

4:02 trap_exit: you're using CLJS I assume?

4:04 trap_exit: ambrosebs: indeed

4:04 ambrosebs: can you keep a secret?

4:04 ambrosebs: I'm writing a real time LaTeX / MathJax editor in cljs

4:05 ambrosebs: trap_exit: epic

4:05 trap_exit: actually, the TeX algorithm is easy

4:05 Glenjamin: how are you rending the LaTeX?

4:05 trap_exit: oh, I'm not rendering LaTeX

4:05 I'm writing a WYSIWYG equation editor

4:05 it's not TeX compatible

4:06 using svg text nodes to impelment hbox / vbox / frac / matrix environments

4:06 apaprently the chrome gc hates this though

4:06 ambrosebs: trap_exit: well I hope to service your type checking needs soon enough.

4:07 trap_exit: ambrosebs: oh shit

4:07 you're the author of core.typed

4:07 for your master's thesis

4:08 ambrosebs: undergrad honours, but yea :)

4:08 trap_exit: did the kick starters pan out? are you working on this full time?

4:09 ambrosebs: trap_exit: yes all went great.

4:09 trap_exit: one thing I couldnt figure out how ot express in core.typed

4:09 ambrosebs: trap_exit: starting PhD at Indiana Bloomington in a few months

4:10 TEttinger: how does a kickstarter for an open source project work? stretch goal, add js-style weak typing at $40,000

4:10 trap_exit: is to be able to say "(:tag %) is :hbox-node"

4:10 so right now, in my "object type system, " I do shit like {:tag :hbox-node ...} , {:tag :frac ... }

4:10 where basically (:tag object) = "type of object"

4:10 is there a way to express this in core.typed?

4:11 ambrosebs: are you goign to Indiana to work for the people who created racket scheme?

4:11 ambrosebs: trap_exit: not sure what you mean. (class obj) = class of object

4:12 trap_exit: right, this works for thigns like NUmber, Float, String ...

4:12 ambrosebs: trap_exit: yes, working with the Typed Racket guy and the miniKanren guy

4:12 trap_exit: but in core.typed, can you declare your own types? (that are not clojure builtins) ?

4:12 so in C, we can do struct Point {int x, int y};

4:12 in clojure, I do stupid thigns like {:tag point, :x 20 :y 30}

4:12 ambrosebs: trap_exit: it supports deftype/defprotocol

4:12 and also HMap

4:13 which (HMap :mandatory {:a Number})

4:13 is {:a 1}

4:13 for example

4:13 trap_exit: *thinking*

4:13 ambrosebs: you can do (assoc {:a 2} :b 'a) :: (HMap :mandatory {:a Num :b Sym})

4:13 and other ops

4:13 trap_exit: can you point meat docs for this?

4:14 ambrosebs: maps with kw keys are special

4:14 trap_exit: I clearly did not read this section

4:14 ambrosebs: trap_exit: docs are sparse but https://github.com/clojure/core.typed/wiki/Types#heterogeneous-maps

4:15 trap_exit: there's a video floating about..

4:15 https://www.youtube.com/watch?v=CFRVW7vGwLY

4:16 trap_exit: *thinking*

4:16 ambrosebs: trap_exit: operations like merge/assoc/dissoc/get are supported, get-in/update-in/assoc-in are WIP

4:16 TEttinger: nice work btw on typed clojure, ambrosebs. I haven't used it but it gets so much coverage here, I'm impressed

4:16 ambrosebs: TEttinger: cheers

4:18 trap_exit: a bigger example https://github.com/frenchy64/tools.analyzer/blob/typed/src/main/clojure/clojure/tools/analyzer/typed.clj

4:18 trap_exit: ambrosebs: I think I underestaimed core.typed

4:20 ambrosebs: correct me if the followin gi swrong. With HMap, I can specify that the value assocaited with a certain key has a certain type.

4:20 However, I wnat to require that the value assocaited with a certain key has a certain _value_.

4:20 So for example, I want to say the type "HorizNode" consists of objects where (:tag obj) = :horiz-node

4:21 ambrosebs: trap_exit: yes that's supported

4:21 you can dispatch on a :tag or :op key in a multimethod for example

4:21 see the last link, there's an :op key

4:21 with a literal keyword value

4:21 trap_exit: (HMap :mandatory {:a Num}) <-- this shows requiring for type, not value

4:21 ambrosebs: g2g, but have a browse of the last link

4:21 trap_exit: sure

4:21 thanks

4:22 mpenet: I think you can do (HMap :mandatory {:a (Value :something)})

4:22 might be cleaner to define a type alias for these kind of values if there are multiple choices btw

5:00 phillord: I want to benchmark a longish running process -- trying criterium, but it doesn't return (I'm guessing that there is too much variation). Is there a way to limit the maximum number of runs? The process takes about 2 seconds, although I'd like to benchmark a 60 second one also

5:01 Glenjamin: try criterium/quick-bench perhaps?

5:01 phillord: this was quick bench:-)

5:03 clgv: phillord: maybe a profiler approach is better suited here. just repeat the process 30 times and let jvisualvm or yourkit instrument the code and measure time consumption

5:03 * phillord nods

5:04 phillord: the problem is that I am timing a process that is loading code, so I am worried that the instrumentation is going to confuse this

5:08 clgv: phillord: just tried the following (time (quick-bench (Thread/sleep 2000)))

5:08 phillord: oh, that works, but then the variance on Thread/sleep 2000 is tiny

5:08 clgv: phillord: criterium reports Evaluation count : 6 in 6 samples of 1 calls.

5:09 phillord: I thought you had problems with 2secs as well?

5:09 took 42secs of runtime

5:09 phillord: hmmm

5:13 curious, wonder why my code never seems to return

5:15 clgv: phillord: well let's put some variation in it an see what happens: (time (quick-bench (Thread/sleep (+ 2000 (- (rand-int 1000) 500)))))

5:15 similar result Evaluation count : 6 in 6 samples of 1 calls.

5:16 phillord: yes

5:16 so, the count number is fixed it appears -- code suggests the same

5:16 clgv: who? no it is adjusted due to some statistic

5:16 -who

5:18 (time (quick-bench (inc 42))) => 241525044 in 6 samples of 40254174 calls.

5:18 the samples seem to be fixed

5:19 phillord: yes

5:20 there is a :samples option in *default-quick-bench-opts* -- it's "6"

5:20 clgv: ah right^^ but the number of evaluations is adjusted^^

5:21 phillord: ah

5:22 clgv: 6 vs 241525044

5:22 phillord: so if you (quick-bench (inc 42)) is makes 10^6 calls

5:22 or 10^7

5:23 guess I should just run it 20 times and average the results

5:26 clgv: yeah since there is probably a lot of variantion in the runtimes for (inc 42)

5:26 *variation

5:27 phillord: running my process at the repl gives me a lot of variation also

5:29 clgv: phillord: yeah, criterium uses a jit warmup to reduce that

5:29 phillord: and loading lots of code probably doesn't help

5:30 clgv: you load the code in each call?

5:30 is that some kind of DSL constructing programms?

5:30 * phillord nods

5:30 phillord: not programmes technically, but a knowledge base

5:32 having the knowledge base be a pile of code provides some nice features -- you can run it in an IDE, eval bits of it and so on

5:32 disadvantage, when you read a file with a big knowledge base, clojure parses, *compiles* and then runs it

5:33 I shall fall back on custom bench marking I think

5:33 thanks for the advice

5:53 master_op: hello, what is the difference between {:a 1} and #{:a 2}

5:53 i mean the "#" symbol

5:54 CookedGr1phon: the first is notation for a mapping of :a to 1, and the second is notation for the set of :a and 2

5:55 master_op: but the both are HashMap ?

5:55 yes or no ?

5:55 Glenjamin: no

5:55 CookedGr1phon: no, the second is a set

5:55 Glenjamin: the latter is a hashset

5:55 ,(type #{:a 1})

5:55 clojurebot: clojure.lang.PersistentHashSet

5:55 master_op: ok

5:55 Glenjamin: ,(count #{:a 1})

5:55 clojurebot: 2

5:57 master_op: thank you very much

6:03 ivan: any way to lein cljsbuild auto just one build? lein-figwheel is handling my non-advanced build

6:03 CookedGr1phon: do once instead of auto?

6:04 ivan: that would take 40+ seconds each time instead of 9 :)

6:04 CookedGr1phon: oh, you mean one build *configuration*

6:04 sorry, misunderstood

6:05 ivan: yeah

6:05 CookedGr1phon: make a different lein profile with just the bits you want to build and with-profile that

6:06 ivan: thanks, will do

7:36 HolyJak: Hello folks! Is there a way to write "(if (pred x) (f x) x)" without repeating x all the time? x is a computed value and I would prefer something like (condp2->> x (pred) (f)) over (let [x …] (if (pred x) (f x) x)). Is there something like condp2? Thx!

7:37 ohpauleez: HolyJak: You could use cond->

7:37 (cond-> x (pred x) f)

7:38 HolyJak: this stil requires let: (let [x ..] (cond-> x (pred x) f)) and thus is not better than the if version

7:38 ohpauleez: nope

7:38 well, yes

7:38 HolyJak: as I mentioned, x is not actually a var, it is an [expensive] expression (think of (count-users-in-db))

7:39 ohpauleez: right, so I'd always do it once, in a let, regardless of what I was doing afterwards

7:40 HolyJak: yeah, but if there was such a thing as condp2, it would result in shorter and nicer code than wrapping it with let :-)

7:41 ohpauleez: If the few characters matter, and you are sure the team has the context (the implied let), then write a macro

7:41 agarman: HolyJak: shouldn't be too difficult to write your own condp2

7:42 HolyJak: I know I can do that, I was just curious if there already is a way to achieve it; I think it is not so good to introduce another syntactical element just because I am not fond of let :-)

7:43 agarman: have you looked at as->

7:43 ,(doc as->)

7:43 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

7:43 agarman: or cond->

7:43 ohpauleez: He'd need as-> and cond ->

7:44 agarman: yeah

7:44 HolyJak: right

7:44 ohpauleez: Personally, I'd just do the let and if, it's not a lot of typing, and it's easier to comprehend at a quick glance

7:45 HolyJak: I could also do (-> (count-users) (#(if (pred %) (f %) %) but that is ugly too

7:45 ohpauleez: the threading macro creates a let anyway

7:45 HolyJak: I will *let* it be then :). Thx!

7:46 ohpauleez: just make a function cond-apply that takes two functions: the initial value function, and the predicate

7:46 a better name might be if-apply

7:47 or whatever domain name fits for the app

7:47 the other technique I use a lot here is change the logic around so I can nil pun

7:48 HolyJak: I think it is better to stick to what Clojure already provide and devs know rather than inventin my own fns/macros that do not add any significant value

7:48 ohpauleez: I think that's a good idea :)

7:48 gfredericks: speaking of which hooray for clojure.core/update :)

7:49 HolyJak: May be I could use some-> if I make sure that the predicate iether returns nil or the original value...

7:49 ohpauleez: right

7:50 if you nil pun at the other level in your code, you make the caller handle the conditional

7:50 agarman: anyone know of a nice alternative to Kafka that has absolutely no Scala garbage in it?

7:50 ugh!

7:50 HolyJak: Could you elaborate, pls?

7:51 ohpauleez: speaking of "hidden" functionality, I never realized `conj` was such a super function until recently. And I'd been doign Clojure stuff for years now

7:54 HolyJak: This might give you some idea:

7:54 gfredericks: ohpauleez: because of the polymorphism? or interaction with the update model?

7:54 ohpauleez: ,(let [x 5] (and nil (inc x)))

7:54 clojurebot: nil

7:54 ohpauleez: where `nil` is the return of your predicate

7:54 and `inc` is your f

7:55 gfredericks: I never knew it handles so many cases (polymorphic), like maps

7:55 HolyJak: I see, thx

7:55 gfredericks: ah right

7:55 ohpauleez: ,(conj {:a 1} {:b 2})

7:55 clojurebot: {:b 2, :a 1}

7:55 ohpauleez: (conj {:a 1} [:b 2])

7:55 and so on

7:55 gfredericks: oh that first one is terrible

7:55 ohpauleez: yeah

7:55 right?!

7:56 gfredericks: that's what we have merge and into for

7:56 ohpauleez: it's polymorphic even on the second arg

7:56 gfredericks: that's a special case

7:56 and a bad one; aside from that, conj puts things into collections

7:57 ohpauleez: Agreed - I only recently stumbled onto this, where I actually needed all of that behavior in a project

7:57 gfredericks: you needed the map/map thing?

7:57 ,(conj {} 3)

7:57 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

7:58 gfredericks: ^ that weird edge case is responsible for this error messages being so confusing

7:58 ohpauleez: yeah, I was writing a function called conj-merge, when Timothy Bladbridge kindly told me about conj's other side

7:58 wow, Baldridge

7:58 (typo)

7:59 gfredericks: I wonder if anybody has a blag post surveying clojure's data structures from an inheritance perspective

7:59 e.g., "this is the group of things you can do this with"

7:59 giant ven diagram

8:00 ohpauleez: I think there's an old one from Sierra

8:01 * gfredericks surfs down the information superhighway over to stuartsierra.com

8:02 * ddellacosta would like to read anything like that as well

8:03 ohpauleez: And I think maybe Alan Malloy wrote a blog post years ago on collections vs seq vs sequential

8:04 gfredericks: he doesn't have a list of titles.

8:05 ohpauleez: gfredericks: Might have an example here: https://github.com/stuartsierra/class-diagram

8:06 gfredericks: ah ha

8:06 nice

8:07 does anybody know off the top of their heads what is the CinC approach to all the shared impl that CinJ uses abstract classes for?

8:14 here's a curiosity in the java code: clojure.lang.Settable

8:14 an interface only implemented by Var and as far as I can tell not used anywhere else

8:19 michaelr525: hi

8:20 with cider, how can I send an expression to the repl, execute it there, and see the result printed in the repl?

8:20 I've seen it done somewhere but could not find a shortcut in the cider readme

8:24 mpenet: ctrl-c-c does this, well you see the result in the minibar, but if your form prn it sends it in the repl

8:24 philandstuff: wow, (deref) works with any java.util.concurrent.Future implementor, not just clojure (future)s

8:25 mpenet: menubar -> minibuffer

8:27 qerub: philandstuff: For the record: it also works with any IBlockingDeref impl.

8:35 gfredericks: ,@3

8:35 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.concurrent.Future>

8:36 gfredericks: ^ funny error message

8:36 ,*clojure-version*

8:36 clojurebot: {:major 1, :minor 6, :incremental 0, :qualifier nil}

8:36 gfredericks: I think I might have made a patch to improve that error msg

8:48 clgv: gfredericks: lol that CinJ abstract classes finally will give us a method to derive objects for internal implementations (throwing pennies in a wishing well)

8:49 qerub: clgv: What's CinJ?

8:50 clgv: qerub: gfredericks used it to contrast CinC with the current Clojure implementation

8:51 gfredericks: clojure in java

8:51 java-clj

8:51 clava

8:51 javajure

8:51 clgv: :P

8:51 clj-java ;)

8:51 gfredericks: public static void clojure(String[] args){}

8:52 clgv: oh that would be useful ;)

8:56 qerub: clgv, gfredericks: Oh, I see. Thanks. :)

8:58 mercwithamouth: sort of cliche but i think it's time for me to write a blogging engine in clojure

8:58 gfredericks: there comes a time in every programmer's life...

8:58 qerub: What have you heard about moving core Clojure abstractions (like ISeq and IBlockingDeref) to protocols? Is it on a wishlist somewhere or is it bad idea because of the little extra overhead?

8:58 gfredericks: qerub: I think that's just lumped with CinC

8:58 qerub: mercwithamouth: Make sure to implement your own web framework on the way. ;)

8:58 gfredericks: i.e., not planned for any earlier

8:58 mercwithamouth: qerub: no!

8:59 qerub: gfredericks: OK, makes sense. Thanks.

8:59 mercwithamouth: i have a much cooler project...but to get the basics down...

8:59 clgv: mercwithamouth: is that still hip? shouldnt one write his own nosql db right now? :D

9:03 noncom|2: the latest hip is to write clojure in clojure

9:03 gfredericks: reiddraper: I'm starting to really want an extension to this for macro that allows independent generators, besides tuple

9:03 noncom|2: btw, are there any known OSs written in Clojure?

9:04 gfredericks: an easy one I just thought of after typing that would be (for [:parallel [v1 g1, v2 g2, v3 g3]] ...)

9:04 I guess I just don't like the way using tuple arranges the code

9:05 heck I'm gonna go write that for test.chuck right now.

9:16 noncom|2: is there any way to measure the size of current clojure runctime? i mean, not anything particulary exact, but for example, amount of registered names, namepsaces or something alike. i need this just for reference

9:17 agarman: ,(count (ns-map *ns*))

9:17 clojurebot: 709

9:17 noncom|2: oh that is nice i think

9:18 gfredericks: that's the number of names available in your current namespace

9:18 noncom|2: and what about doint that from Java?

9:18 gfredericks: ,(count (all-ns))

9:18 clojurebot: 9

9:18 noncom|2: or something alike

9:18 like RT.registeredNames.length or something like that?

9:19 gfredericks: noncom|2: look at the clojure.java.api.Clojure class in clojure 1.6 for calling anything from java

9:19 noncom|2: no no i think that my aim is not to call clojure, but use java to get some info on runtime. just what would be the best RT fields to monitor?

9:20 thanks for the reference to the new 1.6 java API btw! i have come across it but did not yet look in detail

9:20 gfredericks: well calling clojure can help you do that

9:21 but if you really wanna dig into clojure internals, I think the Namespace class has a static field with all the namespaces

9:21 ,clojure.lang.Namespace/namespaces

9:21 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to find static field: namespaces in class clojure.lang.Namespace, compiling:(NO_SOURCE_PATH:0:0)>

9:21 noncom|2: you see, i am just trying to display progress of loading all clojure scripts in a java program. the user should see a growing number and he knows the approx top size and sees the speed of loading

9:21 hmm

9:22 gfredericks: not sure why the access from clojure there doesn't work

9:27 noncom|2: gfredericks: i think it will work, but my point is that the clojure runtime will be busy with loading itseld with all the scripts being loaded and asking it to perform a function like that might hinder it.. or am i mistaken and all will work just fine?

9:27 afaik asking for a datastructure size is ok, but calling functions on it... you see, the loading even happens in a dedicated thread and such...

9:28 i don't know really but it seems like invoking clojure during loading clojure will cause some complications.. i møïðå be wrong

9:28 *might

9:29 gfredericks: I don't think it would

9:30 noncom|2: ok, i will try this way then :)

9:31 gfredericks: clojure tries pretty hard to be concurrency-friendly

9:32 noncom|2: right, and I didn't think, but calling invoke on a clojure var is clojure domain, not java domain, so concurrency stability should be in place then

9:41 gfredericks: reiddraper: done; the second piece of code here is an example usage: https://github.com/fredericksgary/test.chuck#for

9:41 reiddraper: gfredericks: yeah that seems like a neat addition to test.chuck/for

9:42 gfredericks: seems like a nicer approach to the independence issue

9:43 reiddraper: would you like a patch to make (gen/elements #{:some :set}) work?

9:46 reiddraper: gfredericks: something just like calling (into [] ...) on whatever argument you pass in?

9:46 gfredericks: seq would be sufficient

9:46 reiddraper: gfredericks: yes

9:46 gfredericks: but a vector might be a good idea

9:47 reiddraper: seems fine to me

9:47 gfredericks: for faster indexed selection over time

9:59 clgv: gfredericks: uhh I like your `for`

9:59 (inc gfredericks)

9:59 lazybot: ⇒ 63

10:00 gfredericks: me too! I use it all the time

10:00 clgv: are you trying to get it patched into test.check? I'd say it belongs there since it is widely applicable

10:02 gfredericks: clgv: http://dev.clojure.org/jira/browse/TCHECK-15

10:02 feel free to upvote ;-)

10:02 clgv: done ;)

10:02 gfredericks: I think reid is in favor

10:04 clgv: does the new :parallel clause seem like a good idea?

10:04 I only thought of it an hour ago

10:04 clgv: gfredericks: parallel transforms to gen/tuple?

10:05 gfredericks: right

10:05 pretty simple transform, it just means you have your the name next to the generator

10:05 rather than names and generators segregated like with tuple

10:06 clgv: yeah. I like it. in principle I'd have called it :let but then it conflicts with the normal `let`

10:07 gfredericks: is it a "real" `for` or is each keyword only allowed once?

10:07 gfredericks: clgv: if you think of a better name, let me know; :parallel is sooper long

10:08 clgv: it's "real" in that sense

10:08 I didn't support any keyword as an initial clause except for :parallel

10:08 clgv: humm :gen-let wouldnt be that much shorter...

10:08 gfredericks: hopefully also with meaning as evident as :parallel

10:09 clgv: :gen ?

10:09 humm no

10:11 gfredericks: why not just :tuple?

10:16 HolyJak: Question: I need to pad a vector to certain length, using a default value if not there; is this the optimal way to do it? ,(reduce-kv (fn [vec idx val] (assoc vec idx val) ) [:default :default :default :default] [1 2])

10:16 Question: I need to pad a vector to certain length, using a default value if not there; is this the optimal way to do it? ,(reduce-kv (fn [vec idx val] (assoc vec idx val) ) [:default :default :default :default] [1 2])

10:17 dabINclj: hello I created a new project with lein and opened it in LightTable

10:17 I then added the clojure.data.json dependency

10:17 but when im' trying toevaluate now i get: no such namespace....

10:18 HolyJak: dabINclj: you either need to restart the repl, after having added a new dependency, or use a lib that can do it at runtime

10:18 dabINclj: in my source file i but this (ns tweedlsclj.core (require '[clojure.data.json :as json]))

10:18 HolyJak: how i restart the REPL?

10:20 HolyJak: well, how did you start the repl? using "Eval editor contents" in LT? BTW the lib I mentioned is https://github.com/pallet/alembic

10:20 gfredericks: clgv: I thought of that; not strongly opposed

10:20 clgv: I do think anything like :let would be misleading, since clojure.core/let is exactly NOT parallel

10:21 clgv: gfredericks: would fit better since :parallel suggest more than just :tuple

10:21 gfredericks: yeah, mentioning :let was just thinking aloud ;)

10:21 gfredericks: yeah; I'm not sure about :tuple though because the fact that it uses gen/tuple is sort of an impl detail -- the user doesn't actually handle a real tuple at any point

10:21 HolyJak: In LT, you start the repl by command-shoft-enter or by executing the "Eval editor contents" action. You restart it by exec. the action "Editor: Disconnect clients attached to editor" (the repl is the client)

10:23 dabINclj: HolyJak: thanks that worked

10:24 gfredericks: I wonder if this for macro yields more readable generators than is possible with erlang/haskell

10:24 at least without doing something appaling with templates

11:01 otrewyi191: !~

11:51 philandstuff: I've been trying to use test.check with knossos to find concurrency issues in code

11:51 here's a noddy piece of code with a concurrency bug: https://github.com/philandstuff/test-check-knossos/blob/master/src/philandstuff/test_check_knossos/machine1.clj (it's representing a deli counter ticket machine)

11:51 here's my test.check + knossos code: https://github.com/philandstuff/test-check-knossos/blob/master/test/philandstuff/test_check_knossos/machine1_test.clj

11:56 it works in that it consistently finds that there is a race condition, but it doesn't always shrink to the same value (as the race condition doesn't always manifest)

11:56 something else I want to improve is to have a failing test report the observed history rather than the test stimulus, so you can see the values that were inconsistent

11:56 feedback welcome :)

11:59 TimMc: Fare: Did you end up getting what you needed for the backdoor?

12:00 Fare: TimMc: I believe I do.

12:00 Now I'm wondering how/where to publish this trivial file.

12:01 TimMc: github? public repos are free.

12:01 Fare: maybe put it as a project on github?

12:01 reiddraper: philandstuff: very neat

12:01 Fare: or would it be a fine contrib to an existing clojure project?

12:01 TimMc: What does it do now?

12:02 I mean, did you end up doing classloader stuff?

12:03 eflynn: hi

12:03 philandstuff: reiddraper: thanks

12:46 Fare: what's a good name for my dynamic loading of clojure?

12:46 DynLoadClojure.java is the current name

12:48 sandbags: depends if it's a dynamic loading of clojure or a dynamic clojure loader

12:52 Fare: sandbags: what's the difference?

12:53 I'm loading clojure.jar then using load-string on arguments

12:54 sandbags: I guess I was, in a hopefully light-hearted way, alluding to DynLoadClojure not being very noun-like

12:56 if the thing is a loader, i'd call it a loader (for example)

12:56 but i have a habit of being flippant in all the wrong contexts

12:56 Fare: ClojureLoader ?

12:56 arrdem: loadjure

12:56 Fare: LoadClojure

12:57 rasmusto: cloadjure

12:57 Fare: ok for LoadClojure

12:57 arrdem: (inc rasmusto)

12:57 lazybot: ⇒ 12

12:57 sandbags: arrdem, rasmusto ++

12:57 Fare: if it's a project with a single file called LoadClojure.java, should the git repo also be called LoadClojure ?

12:58 sandbags: oh i see we are objects

12:58 Fare: (inc Fare)

12:58 lazybot: You can't adjust your own karma.

12:58 sandbags: i guess we are atoms since no dosync

12:58 Fare_tmp: (inc Fare)

12:58 lazybot: ⇒ 1

12:58 arrdem: (dec Fare) ;; no cheating

12:58 lazybot: ⇒ 0

12:59 Fare: :-)

12:59 arrdem: :P

12:59 Fare: (inc DoesNotExist)

12:59 lazybot: ⇒ 1

12:59 Fare: (dec Fare)

12:59 lazybot: You can't adjust your own karma.

13:01 sandbags: (deref sandbags)

13:01 oh well

13:01 arrdem: I should PR lazybot to add deref and (doseq [name & names] (inc name))

13:01 but that's work

13:02 llasram: $karma sandbags

13:02 lazybot: sandbags has karma 0.

13:02 gfredericks: arrdem: while you're at it, support (swap! arrdem inc)

13:03 sandbags: at the very least @sandbags surely :)

13:03 arrdem: gfredericks: only after I support (swap! ideas conj "support (swap! arrdem inc)")

13:03 'cause we really need a community ideas list..

13:05 gfredericks: let's make a crypto currency so we can use the blockchain to keep track of stuff

13:05 arrdem: why would we do that when we have trusted bots...

13:06 gfredericks: to get rich

13:06 arrdem: no that's what dogecoin is fo

13:07 Fare: https://github.com/fare/LoadClojure

13:08 llasram: Fare: copyright Google, Inc?

13:08 rasmusto: (inc google)

13:08 lazybot: ⇒ 2

13:08 Fare: that's my employer, and these are work hours.

13:10 llasram: I see

13:10 sandbags: Fare: suggestion: delete the commented out code

13:11 leave it in a branch if it's something you want to keep track of

13:12 Fare: I'll delete it. I wanted it in the initial commit, though

13:12 so it's there

13:12 rasmusto: I like making dangling branches and stashes that I never push to origin

13:15 llasram: Fare: OOC, what's your goal with this project? Just to have some example code up showing this technique?

13:15 aav: any ideas on this: http://stackoverflow.com/questions/23833526/messages-publish-before-subscribe-in-core-async ?

13:17 Fare: llasram, I was thinking of using it in a project where I do NOT want to distribute clojure statically linked in the application, but I am able to instantly add clojure to interactively debug the application and explore it.

13:19 llasram: Fare: THat sounds interesting. Is the plan to then just include this source directly in such applications, or do you intend to package this so the loader can be included as a normal dependency?

13:21 sandbags: i feel like i've asked this before but... given there's no dissoc-in in the std.lib i assume i am missing some smart way to do this that's already provided?

13:22 arrdem: sandbags: I think it's in the incubator at this point...

13:22 sandbags: arrdem: ah, i saw something about a version in clojure.contrib (which i think is old) so assumed it wasn't needed

13:22 rasmusto: (dissoc-in [:a :b :c] {:a {:b {:c 1}}}) like that?

13:23 sandbags: yah

13:23 arrdem: sandbags: there's an argument to be made that dissoc-in is just update-in dissoc, which is why I don't think it's in core at present.

13:24 sandbags: yeah that makes sense i guess

13:24 although i think dissoc-in reads nicer and has a symmetry that i appreciate, but i can understand the argument

13:24 thanks

13:24 Fare: llasram, this LoadClojure class would be shipped in the application, and enabled only in development environment.

13:25 llasram: coo

13:25 Fare: at least that's my current plan.

13:25 rasmusto: ,(update-in {:a {:b {:c 1}}} [:a :b] dissoc :c)

13:25 clojurebot: {:a {:b {}}}

13:28 rasmusto: ,(let [dissoc-in (fn [m ks] (update-in m (butlast ks) dissoc (last ks)))] (dissoc-in {:a {:b {:c 1}}} [:a :b :c]))

13:28 clojurebot: {:a {:b {}}}

13:29 rasmusto: sandbags: ^ ?

13:29 sandbags: rasmusto: nice

13:31 gfredericks: am getting an NPE when I run lein deps :tree; trying to minimize now.

13:31 Fare: ok, now to use my new LoadClojure class...

13:33 arrdem: cloadjure

13:35 gfredericks: okay I see -- if a dependency is duplicated in the main deps list and in the dev deps list, I get an NPE

13:35 anybody have any reason to think that's not a bug?

13:35 gtrak_: (inc arrdem)

13:35 lazybot: ⇒ 28

13:35 arrdem: gtrak_: that was rasmusto not me

13:36 * rasmusto turns hat backwards

13:36 gtrak_: cloadjure?

13:36 grimoire: (dec arrdem)

13:36 lazybot: ⇒ 27

13:36 llasram: gfredericks: I think that's already been fixed...

13:36 grimoire: (inc rasmusto)

13:36 lazybot: ⇒ 13

13:37 gtrak_: arrdem: ha, nice trick.

13:37 gfredericks: llasram: upgrading now

13:37 arrdem: gfredericks: karma only be created and preserved, not destroyed.

13:37 llasram: gfredericks: Well, fixed in master

13:37 gfredericks: roger

13:37 okay thanks

13:37 arrdem: gfredericks: except for so, who is the karma sink in the channel

13:37 gfredericks: (dec so)

13:37 arrdem: (dec so)

13:37 lazybot: ⇒ -20

13:37 ⇒ -21

13:38 gfredericks: why are we decing so?

13:38 gtrak_: (dec so)

13:38 lazybot: ⇒ -22

13:38 llasram: gfredericks: https://github.com/technomancy/leiningen/pull/1504

13:38 arrdem: oops. sorry gfredericks I meant gtrak

13:38 gtrak_: we need to follow a convention, trak.g fredericks.g

13:39 namespacing issues again.

13:39 gfredericks: why is that better?

13:39 then you'd conflict with anybody whose last name starts with t

13:39 gtrak_: easier to parse as a tree.

13:39 gfredericks: UUIDs for everybody

13:40 pjstadig: UUIDs!

13:40 gfredericks: ,(str "Gary Fredericks will now be known as " (java.util.UUID/randomUUID))

13:40 clojurebot: "Gary Fredericks will now be known as 96b0a14d-dcb9-437f-b701-fd17e856d084"

13:40 gfredericks: phew no swear words

13:40 arrdem: nics are only 16 chars on freenode

13:40 so not quite uuids

13:41 pjstadig: http://clojure-log.n01se.net/date/2011-09-12.html#17:16c

13:41 gfredericks: pjstadig: woah that is back in the gfrlog days

13:41 and amalloy was still stoked about lazybot's ?? feature

13:42 AND it was pjstadig's first karma

13:42 llasram: I'm impressed by the number of people who are still around

13:42 gfredericks: that must be why he kept the link around

13:42 pjstadig: haha i was just seeing that

13:42 $karma pjstadig

13:42 lazybot: pjstadig has karma 5.

13:42 Fare: yay for urbit-style pronounceable UUIDs.

13:42 pjstadig: :(

13:42 llasram: (inc pjstadig)

13:42 lazybot: ⇒ 6

13:42 arrdem: Fare: yay urbit!

13:49 clearly if cloutjure ever rises from the grave the first step is to give everyone a uuid and then associate usernames to uuid'd "individuals".

13:51 gtrak_: creatjure

13:51 rasmusto: I have an idea: "jure"

13:51 arrdem: jurejure?

13:51 gtrak_: fjurejure

13:51 :-)

13:51 arrdem: $LEIN_IRONIC_JURE can go stuff it

13:51 rasmusto: fijjure

13:51 gtrak_: pronounced 'furor'

13:52 arrdem: rasmusto: drop one j and you're golden

13:52 fijure... hehe

13:52 rasmusto: new church: clojure conJREgation

13:52 pjstadig: i actually like jurejure as a project name

13:53 gfredericks: clojurebot: LEIN_IRONIC_JURE is false

13:53 clojurebot: Roger.

13:53 gtrak_: fjureor

13:53 gfredericks: clojurebot: EDITOR is emacs

13:53 gtrak_: there.

13:53 pjstadig: might as well go palindromic: erujjure

13:53 clojurebot: You don't have to tell me twice.

13:53 rasmusto: EDITOR?

13:53 clojurebot: EDITOR is an out-moded belief system

13:53 arrdem: gfredericks: that's funny because "false" is true.

13:53 gfredericks: clojurebot: HOMEDIR is /home/joey

13:53 clojurebot: Ack. Ack.

13:53 gfredericks: arrdem: I thought it might be but didn't care to bother finding out

13:54 clojurebot: DESKTOP_SESSION is gnome-xmonad

13:54 clojurebot: Alles klar

13:54 arrdem: clojurebot: clojurebot is a database of lies, jokes and half truths

13:54 oh. right. still bot ignored.

13:54 rasmusto: I've been klar my whole life

13:54 gfredericks: arrdem: you got blacklisted by clojurebot?

13:55 arrdem: gfredericks: I think hiredman ignores me and clojurebot does as a result.

13:55 gfredericks: clojurebot: SSH_AGENT_PID is 2155

13:55 clojurebot: You don't have to tell me twice.

13:56 pjstadig: hiredman ignores a lot of people

13:57 arrdem: Bronsa: `:argslist` is just propagated up of `:ret` has a `:argslist`? I'm surprised to see an `:op :let` with `:argslist`.

13:57 s/of/if/g

14:01 gtrak_: luxjurey sedjan

14:01 Bronsa: arrdem: don't be surprised :P if an :op :let has :arglists it means that it's body returns a var that has :arglists

14:02 arrdem: Bronsa: okay that's how I was reading it.

14:02 gtrak_: mjureatic acid

14:03 Bronsa: arrdem: some passes might leave some garbage attributes in the AST, I really don't care.

14:03 arrdem: Bronsa: yeah I don't think there's a good way to enforce cleaning up your mess...

14:04 Bronsa: arrdem: just.. ignore it :P

14:04 arrdem: Bronsa: nah I'll go all angry haskeller and write an ast "cleaner" that'll purge any key not in the spec :P

14:05 Bronsa: haha

14:05 gtrak_: arrdem: sounds like a good use-case for mjureatic acid.

14:06 or hydrocljoric

14:06 arrdem: Bronsa: May I trouble you for feedback on handling closed over top level defs? It's my understanding that top level no def forms (ifs, lets and soforth) get compiled as function applications and deferred until load time. Is this the case?

14:06 gtrak_: quiet in the peanut gallery.

14:06 amalloy: gfredericks: is this some weird scheme to back up your current shell env?

14:07 arrdem: $SSH_AGENT_PID

14:07 rasmusto: SSH_AGENT_PID?

14:07 clojurebot: SSH_AGENT_PID is 2155

14:08 gfredericks: amalloy: better safe than sorry

14:08 Bronsa: arrdem: are you asking about t.e.j or Compiler.java?

14:08 rasmusto: is there a way to use the match groups when doing regex matching using core.match?

14:09 arrdem: Bronsa: what I'm trying to do here is decide what's legitimate to do to the sort of (let [] (def)) you mentioned two days ago. Since the let will only get evaluated once I kinda want to lift it to top level private defs which will let me play tricks with the let enclosed fns but I'm not sure if that breaks what Compiler.java does.

14:09 Bronsa: I don't think it would

14:09 rasmusto: (match [x] [#"foo(.*)"] <something w/ that group>)

14:10 Bronsa: arrdem: I was thinking about that earlier today and I can't think of a scenario where that would break things either

14:11 arrdem: Bronsa: the closest I could get to was if you had something like (let [x (System/getEnv "Foo")] (def...)), but because of init time that can still be legitimate with let to def promotion so I think it's ok.

14:12 or however you reference environment variables.

14:16 Bronsa: arrdem: well, if I understand correctly, what you're trying to do with the optimizing compiler *requires* separating the compiler environment from the runtime environment so I wouldn't bother about those cases, I'd consider supporting them out of scope for what you're trying to do

14:22 arrdem: Bronsa: hum... maybe. I'm torn between trying to support the load semantics of JVM Clojure which would mean Oxcart should be able to eat any valid JVM Clojure program and saying "oh well Oxcart is gonna break stuff" which is where Tim seems to stand.

14:25 Bronsa: arrdem: I'm with Tim on this one. There's simply no way to support all valid Clojure programs with what you're trying to do, think about intern, eval, ns-interns or stuff like that

14:32 arrdem: Bronsa: I disagree in that I can always fall back to using tools.emitter to do the "right thing" for dynamic code that I can't play tricks with, however you're right that the point of this project is to play tricks and that I should take a "good enough" approach and support a reasonable static stubset of Clojure. walk before I try and run...

14:32 alright. compile scheme programs first...

14:52 trap_exit: what does : $ ./lein repl Exception in thread "main" java.io.FileNotFoundException: Could not locate clojure/tools/namespace/repl__init.class or clojure/tools/namespace/repl.clj on classpath: ... mean ?

14:53 rasmusto: trap_exit: modify ~/.lein/profiles.clj to include that dependency

14:53 trap_exit: rasmusto: I have a dumb question -- what dependency ?

14:53 I need to add a dependency to just use the repl ?

14:53 amalloy: why should he add that dependency if he doesn't know what it is?

14:54 lein shouldn't need it, unless either (a) trap_exit has chosen to use it, or (b) lein packages it itself

14:54 rasmusto: [org.clojure/tools.namespace "0.2.4"]. Assuming you are trying to use it interactively.

14:54 trap_exit: oh, I see where I'm being retarded now

14:54 technomancy: you're using a plugin or something that hasn't declared its deps properly

14:54 trap_exit: amalloy, rasmusto: thanks! :-)

14:55 arrdem: trap_exit: what are you trying to load? because the maintainer should fix his stuff..

14:55 trap_exit: the maintainer is not at fault

14:55 arrdem: kk.

14:55 trap_exit: I'm a retard, and had ":repl-options {:init (use '[clojure.tools.namespace.repl :only (refresh)])}" in my project.clj without requiring clojure.tools.namespace as a dependency

14:55 :-)

14:56 technomancy: you are the maintainer of your own profiles.clj =)

14:56 trap_exit: the maintainer is a retard

14:56 technomancy: been there

14:57 trap_exit: though one thing tht pisses me off

14:57 is how long lein takes to start

14:57 I'm considering getting a 4x quad-core machine with 128 GB of ram just so I don't have to restart lein

14:57 technomancy: I have 4GB of ram and I never restart lein

14:57 except for when I'm working on lein itself

14:58 which is most of the time I'm writing clojure

14:58 rasmusto: I have 512GB of RAM and I restart lein 15 times a day

14:58 technomancy: anyway, https://github.com/technomancy/leiningen/wiki/Faster

14:58 rasmusto: we should chart it to see if there's a correlation

14:58 trap_exit: rasmusto: I was using lein on a digital ocean droplet -- not fun

14:58 llasram: I have half a byte of RAM, which takes a lot of swapping to run lein in

14:59 trap_exit: holy shit

14:59 technomancy: llasram: oh we used to dream of half a byte of ram

14:59 trap_exit: how do you run your OS?

14:59 rasmusto: I run lein entirely in L1

14:59 trap_exit: I wnat a CPU dedicated to running lein

14:59 technomancy: would 'ave been a palace to us

14:59 llasram: trap_exit: the OS is in ROM, obvs

14:59 arrdem: (inc technomancy)

14:59 lazybot: ⇒ 108

15:02 rukor: hi, when i run lein ring server without having aot-compiled, it works, however when i aot-compile, and run it again it says No matching ctor for class compojure.core$if_method$fn__2494. Any ideas?

15:03 cbp: Is there some way to quickly reload java code defined inside :java-source-paths besides restarting the repl?

15:03 arrdem: cbp: I doubt it...

15:03 trap_exit: https://gist.github.com/anonymous/a46f7336e7136fad3a7d <-- waht is goign on here?

15:03 cbp: f

15:03 trap_exit: why is it looking for cljs/user.clj

15:03 llasram: cbp: vinyasa has something to do it

15:03 trap_exit: err, why is it looking for cljs/user.cljs

15:04 llasram: but my one poke at it didn't work, although the approach should

15:04 trap_exit: if I run it from as "lein typed check-cljs", everything works, but when I run it from the repl, I get the above mess

15:04 llasram: Just uses Clojure's dynamic class loader machinary

15:04 machinery even

15:05 cbp: llasram: thanks

15:13 trap_exit: how do I begin to debug "AssertionError Assert failed: Can't find cljs/user.cljs in classpath res cljs.jvm.tools.analyzer/analyze-ns (analyzer.clj:41)" ?

15:13 googling brings up very little

15:13 I suspect I misconfigure project.clj / clojurescript somehow

15:19 is (require 'cljs.user) suppsed to succeed?

15:19 if so, how do I make it succeeed as mine currently fails

15:34 damn t

15:34 is no one around?

15:40 cbp: trap_exit: make sure you have :source-paths ["src"] or something and a file user.cljs inside src/cljs/

15:41 amalloy: trap_exit: #clojure is not a paid support channel with an SLA. if you don't get an answer within 15 minutes, cursing everyone for ignoring you is not the way to encourage helping you in the futuer

15:43 cbp: Does the cider repl have a printstream or something defined anywhere? :-P

15:50 Fare: trap_exit, our SLA is 30 minutes, please wait 15 more minutes before you start cursing.

15:50 stuartsierra: cbp: I think it prints to *out*, but it rebinds *out* on each expression you evaluate.

15:50 Fare: *out* -- are these common-lisp like earmuffs?

15:51 stuartsierra: Fare: more or less, by convention in Clojure they name a dynamic Var, which can be dynamically rebound on a single thread.

15:55 trap_exit: amalloy, Fare: noted

15:56 I want double my money back

15:56 cbp: stuartsierra: thanks

15:57 Fare: reminds me of how the Pythagoricians used to promise people who'd join double their money after they left, if they left.

15:57 then a crook tried to join just for the money, but they wouldn't let him join — so he organized a mob to burn them down.

15:57 trap_exit: cbp: adding a blank file fixed it

15:57 everything works now :-)

15:58 Fare: trap_exit, congrats

16:39 hi

16:39 actually, would clojure itself accept this LoadClojure as a contrib?

16:39 it's < 200 loc, and would probably be more useful there

16:40 technomancy: you don't want to be a contrib

16:40 locks: haha

16:46 stuartsierra: :(

16:51 Fare: I don't want to be a contrib?

16:51 why not?

16:51 or a contrib to a separate project?

16:53 technomancy: "clojure contrib" is a group of libraries under the org.clojure group-id; and I think it's a bad idea to put your own libraries in it for various reasons

16:53 mmitchell: anyone here familiar w/prismatic schema? Trying to figure out the simplest way to get the schema of a schema.core/defrecord value?

16:53 technomancy: if you mean just contributing a feature to clojure itself, that kind of thing doesn't really happen these days

16:55 stuartsierra: Double :(

16:56 benkay: are there any tricks to preserving newlines coming off of a clojure.java.shell/sh call?

16:58 i've naively captured that string of chars and want to render it in a web page, but all the newlines are getting replaced with plain old whitespace.

16:58 technomancy: benkay: by the browser?

16:59 amalloy: i think that's more cynical than is really warranted, technomancy. in the 1.5-1.6 era, getting stuff into clojure proper has gotten easier than before. i think this is mostly alex miller's doing?

16:59 benkay: either the browser or enlive, i'm still looking into that technomancy

16:59 technomancy: benkay: maybe you want a pre tag?

16:59 amalloy: maybe. I would be very surprised if this were included for packaging and security reasons if nothing else though.

16:59 qerub: benkay: …or replace \n with <br/> :)

17:00 benkay: thanks technomancy, qerub.

17:00 technomancy: amalloy: also contributions of entirely new classes coming from someone new to clojure haven't been applied even in the olden days.

17:00 amalloy: yeah, the one specific thing Fare was talking about, i don't expect would be included

17:01 but you were making stuartsierra sad by saying nobody can, or should want to, get any code into clojure, which is too broad

17:01 technomancy: no judgment implied re: the quality of said patch fwiw

17:02 qerub: benkay: You might want to escape < and > in the output too.

17:02 technomancy: amalloy: well, the things I have paid attention to on jira have been the kind of things for which sadface is an appropriate response.

17:04 benkay: qerub: thanks for the advice. i'm fairly confident this lib's output doesn't have angle braces though.

17:06 qerub: benkay: You never know how the code will get reused in the future, but use your judgment. :)

17:07 benkay: ha sage advice.

17:07 hey while i'm here, what's the story on reducing the clojure startup time?

17:08 i was idly considering sponsoring a GSOC project a month or so back, but discovered that the deadline had long since passed.

17:10 technomancy: benkay: there are a bunch of tricks you can use during development to offset long boot times. not sure of progress on other fronts outside dev.

17:11 benkay: yeah but i want it fixed :)

17:12 stuartsierra: There's some background work going on to speed up the Clojure compiler, but it's not easy.

17:13 technomancy: stuartsierra: does the compiler speed affect startup times of AOT'd applications?

17:13 stuartsierra: technomancy: dunno

17:14 Maybe, since one possible technique is lazier loading of individual functions.

17:14 This talk http://www.youtube.com/watch?v=8NUI07y1SlQ has some background.

17:15 technomancy: hm; sounds interesting

17:15 stuartsierra: Most of the time is spent initializing Vars, since Java class files can only store primitives as constants.

17:15 e.g. `(def m {:a 1 :b 2})` has to construct the map on startup.

17:15 technomancy: I expect when you get talking about making changes to how namespaces work there's a huge temptation to overhaul them to become values, or at least more principled areas of mutation.

17:16 stuartsierra: Well, maybe. Vars are the expensive part, I think, not namespaces as such.

17:17 I wish we could just dump memory images like Smalltalk. :)

17:17 technomancy: careful what you wish for

17:17 stuartsierra: heh

17:18 amalloy: i'm a reckless wisher. memory images sounds amazing. why is that bad?

17:18 stuartsierra: In other news, Clojure 1.6.0 finally has a full ZIP distribution at http://central.maven.org/maven2/org/clojure/clojure/1.6.0/

17:18 technomancy: amalloy: from what I understand it's easy to get into a state where it works but you don't know why because you can't get it to work when building from scratch

17:18 amalloy: all the problems of getting slimed, multiplied profusely

17:20 according to some, living in its own world and pretending unix doesn't matter is a big part of what killed smalltalk

17:22 amalloy: killed!? why, just last year i was at a clojure meetup where one guy was evangelizing for smalltalk. it must have literally dozens of users

17:22 technomancy: not-dead-yet.gif

17:24 rasmusto: helper functions never helped anyone

17:25 should I def my helpers? or let/let-fn them

17:25 or defn-?

17:25 qerub: Some CL implementations provide memory images too, for the record. (SBCL: http://www.sbcl.org/manual/index.html#Saving-a-Core-Image)

17:25 rasmusto: defn-??

17:25 lazybot: rasmusto: Uh, no. Why would you even ask?

17:26 technomancy: I like defn-. don't care what anyone says.

17:26 qerub: I think core images can be useful, but the Smalltalk way of depending on it is indeed dangerous.

17:26 rasmusto: technomancy: seems like defn- has the benefit of letting me build up unit tests

17:27 splunk: stuartsierra: thx for mailing list reply.

17:27 technomancy: qerub: yeah, I guess CL shows you can have it without it being the only way.

17:27 stuartsierra: splunk: you're welcome. I wonder what I said.

17:28 splunk: ha! re: `defrecord User [id]` vs. `defrecord User [id name age ... kitchen-sink]`

17:28 * rasmusto pictures a kitten-sink

17:29 splunk: someone needs to invent this.

17:29 stuartsierra: http://www.catsinsinks.com/

17:29 rasmusto: thank you

17:29 (inc stuartsierra)

17:29 lazybot: ⇒ 7

17:30 qerub: mmitchell: A bit late, but re: schema.core/defrecord: it's in the documentation and it is schema.utils/class-schema.

17:31 mmitchell: qerub: ahh, perfect timing actually. Thanks!

17:52 amalloy: man, i just spent forever tracking down what turned out to be (what i regard as) a bug in slingshot

17:53 i had written like (let [[x y z] (repeat 5)] (... (throw+ "stuff is broken")))

17:53 technomancy: I thought ex-info deprecated throw+

17:53 well, superseded

17:55 amalloy: no, throw+ just uses ex-info instead of using its custom Stone

17:56 anyway it turns out that throw+ includes all locals at the throw site in its :environment key, and my sample code there has *four* locals: x, y, z, and vec__auto__3534 or whatever, the last of which is an infinite seq of fives

17:59 and some code somewhere tries to print the exception (i'm still tracking down exactly where that is), including its :environment

18:01 technomancy: what's the throw+ there for though? just habit?

18:01 amalloy: technomancy: well it's throwing more interesting stuff really

18:02 technomancy: oh, to skip the Exception constructor

18:02 amalloy: you mean why am i using throw+ instead of (throw (ex-info ...))?

18:03 technomancy: right; in my head post-1.4 the main value of slingshot is try+

18:04 amalloy: technomancy: i'm not sure how slingshot behaves if you throw your own ex-info objects. its throw+ bundles in a lot of other stuff, which it uses for its own purposes

18:04 technomancy: yeah, I thought throw+ was mainly for backwards-compat with pre-1.4 but I guess it also gets you more goodies.

18:04 amalloy: like, (throw+ "foo") is something like (throw (ex-info {:object "foo", :env (get-all-locals) ...}))

18:05 and then in try+ the catch clauses look at :object to decide which of your exception selectors match

18:05 technomancy: you can try+ against non-slingshot exceptions

18:06 amalloy: anyway, i don't really use slingshot of my own accord, but i work on projects others wrote

18:06 here, there was already a throw+ which was working fine; and in the course of other work i added a (let [[x y z] (repeat 5)] ...) around the existing throw+

18:07 and then suddenly things stopped working, because (.toString e) on a slingshot object tries to print its env

18:07 * Fare finds he has to go through more bureaucratic hoops before he may freely publish LoadClojure

18:26 TimMc: ...speaking of which, I should get legal approval to open-source my URL parsing & manipulation library.

18:28 amalloy: technomancy: how do you try+ against non-slingshot exceptions? something like (try+ (throw (ex-info "test" {:x 1})) (catch :x e e)) doesn't catch it, whereas if i use (throw+ {:x 1}) instead, the form returns {:x 1}

18:30 technomancy: amalloy: you should at least be able to put a predicate in

18:31 amalloy: well, i just did: :x is a predicate

18:31 technomancy: amalloy: sure, it's running (:x (ex-info ...))

18:31 amalloy: but the predicate seems to match against the ExceptionInfo object, and not the map i threw

18:31 technomancy: missing an ex-data call

18:31 right

18:31 which sucks

18:31 amalloy: right

18:31 technomancy: ex-info didn't exist when I worked on slingshot =\

18:32 I really wish it hadn't added the ability to work on non-throwables

18:33 amalloy: i think it's a powerful and useful ability, but one that can be super-confusing

18:33 like, the fact that (catch Throwable t) no longer catches everything was *really* hard to figure out

18:33 technomancy: it's just syntactic sugar over throwing an ex-info with special magic fields

18:33 amalloy: of course

18:35 technomancy: I don't like magic. I should have thought of that before picking this nick though.

18:35 too late now

18:37 amalloy: ugh, implicitly throwing all locals is so frustrating. it's like impossible to scrub all the objects i don't want to throw out of my env. i'm just going to (throw (ex-info ...)) and hope it doesn't break anything

18:45 TimMc: It's also an infosec problem.

18:45 (let [password ...] (throw ...))

18:45 and then it ends up in the logs

18:45 hiredman: amalloy: I think singshot looks under the :object key of the ex-info

18:46 and I am not sure (catch key ...) works with it

18:46 johncash: was playing with core async and realized you can send a channel over it's own channel

18:46 #inception

18:46 amalloy: hiredman: right, it looks there because that's where throw+ would have put it. so like, you can interact with your own thrown ex-info objects without usnig throw+, as long as you throw them exactly the same as throw+ would have

18:46 hiredman: the syntax is rather funky

18:46 johncash: s/it's/its/

18:47 akurilin: Quick question: when writing UTs for functions returning floating point numbers, is an abs + epsilon test the best I can do in clj or is there a "cleverer" approach?

18:47 rasmusto: johncash: it's almost makes sense in this case

18:47 johncash: "it's"

18:47 :p

18:49 johncash: rasmusto: good point

18:50 trying to conceputalize sending a channel over its own channel in my mind causes it to asplode

18:50 conceptualize

19:00 amalloy: johncash: don't forget, pointers to memory addresses are stored in memory

19:01 johncash: (jnc amalloy)

19:01 fuuuuuu

19:01 (inc amalloy)

19:01 lazybot: ⇒ 111

19:09 rasmusto: b-b-but p-p-p-pointers are scary :(

19:09 arrdem: rasmusto: ssssh quiet only void******s now

19:10 rasmusto: ,:pppppppp

19:10 clojurebot: :pppppppp

19:10 {blake}: Heyo...I've been looking for docs on accessing XML through something like (xml-> my-data :parent1 :child3 :grandchild7) but all the stuff I've found on the web is 3-4 years old, and references functions that don't seem to be around in recent versions. So what're peeps doing these days? Xpath?

19:11 dbasch: johncash: it’s no different than sending the gmail source code over gmail

19:12 arrdem: I suppose I only needed void* because void* -> void* is legitimate...

19:13 rasmusto: {blake}: I used clojure/data.xml for writing it, dunno if it'll work in your case

19:14 arrdem: data.xml was reasonable to work with, but as with tools.analyzer you'll want to set *print-length* and the other print limits before you try to visualize anything by accident

19:14 that'll kill cider real fast

19:15 {blake}: rasmuto: Need to read it.

19:15 rasmusto, I mean. =P

19:17 rasmusto: {blake}: I'll assume that's a godzilla reference

19:18 Lajjla: Chousuke, eläätkö vielä?

19:24 {blake}: rasmusto: Ha! Just saw that.

19:25 Would a macro be untoward? (He wondered aloud.)

19:26 amalloy: {blake}: for parsing xml? it seems pretty silly; you should be able to do everything with functions

19:26 once you have done it with functions, if there's unpleasant repetitiveness, you can wrap it up in a macro

19:27 {blake}: amalloy, Well, xml/parse =parses= it. It's addressing it in that fashion that I'm looking for an elegant solution to.

19:31 arrdem: get-in not doing it?

19:36 {blake}: arrdem, Doesn't seem to be. I'm probably overthinking this. The issue is that it's a tree with potentially repeating elements.

19:36 Or maybe underthinking it.

19:36 Not the precisely correct amount of thinking is what I'm getting at.

19:37 arrdem: is swap! defined over transients?

19:37 technomancy: o_O

19:38 * arrdem blithely writes his own update!

19:38 akurilin: Am I correctly understanding that swap! will eventually give up if it's had to roll back too many times?

19:38 arrdem: akurilin: yep it will

19:39 akurilin: I forget what the magic number is tho.

19:39 akurilin: What's a good option then to ensure that it perseveres no matter how long it might take?

19:40 One could serialize the writing to the atom, in theory

19:40 through an agent

19:40 amalloy: huh? no it won't, arrdem akurilin

19:42 akurilin: try: (let [a (atom 0)] (swap! a #(swap! a +' 1 %)))

19:42 that will run forever and ever, because the inner swap forces the outer one to keep retrying

19:44 arrdem: grumble grumble lambda lifting is hard. happy weekend guys.

19:51 akurilin: amalloy: hm I must not really get pmap then. I'm trying to force pmap to conj 100 ints into an atom [] by running pmap against (range 0 100)

19:52 but it's pretty much only saving up to the first 30 values

19:52 So I'm certain I'm doing something dumb here.

19:53 amalloy: laziness

19:54 akurilin: Why would it be lazy if I'm actually running a count on the atom later? Wouldn't that force evaluation?

19:54 clojurebot: It's greek to me.

19:54 amalloy: you're not forcing the pmap at all

19:55 &(let [a (atom []) m (pmap #(swap! a conj %) (range 50))] (Thread/sleep 500) @a)

19:55 lazybot: java.lang.SecurityException: You tripped the alarm! pmap is bad!

19:55 akurilin: Yeah I guess if I run count on the return value of pmap it executes everything

19:55 amalloy: well, whatever. that would likely not do all the work. whereas if you wrapped m in (dorun) or something

19:55 but like, pmap. blugh. there's *always* a better way to parallelize

19:56 akurilin: I'm all ears!

19:56 amalloy: well, for conjing 100 numbers into an atom, the best answer is to do it on one dang thread

19:56 akurilin: This was just a test on my end to validate that the logic that was being used there was not thread-safe.

19:56 amalloy: solutions for real-world problems vary. executors, futures, something

20:13 hiredman: the syntax is rather funky

20:30 akurilin: amalloy_: anyways that was really helpful, thanks again

20:55 jarodzz: #clojure-cn

20:59 trap_exit: argh argh argh argh

20:59 anyone here using core.typed in cljs?

21:15 fortruce_: nick fortruce

21:15 fortruce: oops 0_o

23:02 akurilin: Quick question: is there a preferred method of implementing notifying clients in pubsub web services out there nowadays? As in, polling vs long polling vs some form of push

23:18 Fare: akurilin, uh, I don't know, but probably "use ZeroMQ"

23:21 akurilin: It's more of an academic exercise at this point :)

23:21 otherwise yes, what you said !

23:34 ddellacosta: akurilin: I don't know if this is preferred generally speaking, but after investigating it seems like the best solution *currently* is WebSocket or browserchannel (better compatibility with older browsers, but not an open standard). Server-side events seems to be too sporadically supported as of yet. AJAX hackery is, well, hackery (but what browserchannel falls back to on older browsers I believe).

23:35 akurilin: I guess that's maybe more low-level than you were asking; but wrapping that up in core.async works wonderfully. And you can use core.async on the server side and wrap up something like RabbitMQ to have a relatively seamless messaging system.

23:36 akurilin: ddellacosta: interesting, didn't think of those, thanks for clarifying

23:39 ddellacosta: akurilin: sure thing. Hope that was helpful!

23:40 akurilin: and to be clear, the pubsub part I offload to core.async. It has very nice helpers for doing pubsub simply.

23:44 akurilin: ah fair enough

23:44 Pretty much what that thing was made for huh?

Logging service provided by n01se.net