#clojure logs

2012-06-04

00:00muhooheh "I threw up im my mouth a little...ok a lot...while writing this."
00:00technomancymuhoo: as long as you don't look at the implementation you'll do fine! =)
00:01technomancywe re-use this eclipse s3 publishing module that idiotically hard-codes in the access-control to public.
00:01technomancyI wrote an implementation that wall-hacks it by calling private methods using reflection, and then a co-worker rewrote it "properly" in java
00:03muhoofun times, sounds like.
00:04muhoois there a way to push the repo with acl public?
00:04technomancyoh sure; just use s3:// in the repository URL rather than s3p://
00:04muhooperfect, thanks
00:04technomancyyou don't need s3-wagon-private for that fwiw
00:04technomancybut it's probably better documented
00:04muhoothat's kind of what i thought
00:04muhoomaven repo just looks like a tree
00:05muhoobut then the sha1's need to be generated, all that. better to have a library do it for me
00:05technomancyit's just a pile of static files
00:05technomancyyou can even install to a file:///tmp/whatever repository and copy that to an nginx dir or whatever if you like
00:07muhoousing this tool? or manually?
00:08muhoooh manually will be fine. it's just jar's, pom's, and sha1s
00:09technomancyif you've already got a server and only have one or two jars that never change, that's easiest. if you've got something more complicated look into s3 or nexus
00:09muhoofair enough, thanks for demystifying!
00:09technomancyor start with static files and look into something more sophisticated when you get tired of updating the static files =)
00:43tomojis there already an easy way to hook the compilation events under cljsbuild auto?
00:44craftybonesHello all. Newbie to clojure, at #60something on 4clojure
00:46tomojit does an eval-in-project which launches the compiler watching
00:46tomojoh wait
00:47craftybonesLoving it so far. What's the recommended book on Clojure
00:48tomojcljsbuild already has rudimentary support for notification ;)
00:51technomancycraftybones: I like the oreilly one best
00:51noidi_craftybones, I've only skimmed through O'Reilly's Clojure Programming, but it seems very good http://amzn.com/1449394701
00:51craftybonestechnomancy: thanks
00:51craftybonesnoidi_: thanks
00:52craftyboneswhere all does clojure get used in production?
00:52craftybonesClojure is the first time I've understood lisp in general.
00:53technomancylots of places: http://dev.clojure.org/display/community/Clojure+Success+Stories
00:55PeregrinePDXI also like the Pragmatic Programmer book.
00:55PeregrinePDXAlthough I have the O'Reilly book as well.
01:03HodappThe only reason I use Lisp is because I find it hilarious the sort of mental gymnastics people perform when they think they're superior coders but they can't wrap their mind around why something like Lisp would be useful.
01:03Hodapper, did I say that out loud?
01:04craftybonesHodapp: :) Doesn't matter, I actually get Lisp now as opposed to before when I didn't get Twist
01:05craftybonesHodapp: I meant Lisp. Twist is the project I work on :)
01:07HodappI'm mostly learning Scala right now though.
01:19muhootechnomancy: the jars for these things depend on a foo-parent , which is in a top-level pom.xml . any idea where i'd put that in the tree?
01:19muhooto make this more concrete: http://code.google.com/p/step2/
01:20technomancyhm; sorry, I don't know anything about bare poms
01:25muhoohaha, it worked. i created a dir called step2-parent, put the bare pom in there, and at least pomegranate is happy :-)
01:26muhoohttps://www.refheap.com/paste/2988 , FYI
01:28muhooi am amazed at how much bureucracy is involved in this maven stuff. makes me especially thankful for leiningen.
01:34muhoogotta love java too. a class, that has one constructor that takes a string as an arg, and one public method, that returns the string given in the constructor
01:41Hodappmuhoo: It's.... object-oriented! Right? RIGHT?
01:43ivanmaybe it is not a string but something else with a string payload
01:44bbloommuhoo: facepalm indeed. any class that has 1 method should just be a damn function. that sort of thing drives me nuts
01:49Hodappbbloom: Java doesn't like verbs.
01:50Hodappbbloom: I was also quite annoyed at how many constructs I saw in the C++ mess at work that were like... ITriangleIntersector, implemented by TriangleIntersector, with functions like setTriangle
01:51Hodappmakes optimization and concurrency a bit harder when something normally done by one function is now done by a stateful class.
01:52bbloomHodapp: for sure. but at least in C++ it makes some sense if you've got a constructor/method/destructor trifecta for RIAA. however, even then, you probably want a generalized container like a smart pointer or context object of some kind
03:06lypanovcurrently one part of my app uses agents to "fire it off in background" and another uses "wait for everything to finish" to delay until its finished.
03:06lypanovagents work perfectly for this but id like to also be able to cancel.
03:06lypanovis there a way to coordinate futures to get the same behavior?
03:16gfredericks,(doc future-cancel)
03:17gfredericks&(apropos "future")
03:17lazybotjava.lang.RuntimeException: Unable to resolve symbol: apropos in this context
03:18gfredericks&(clojure.repl/apropos "future")
03:18lazybot⇒ (future-done? future future-call future? future-cancel future-cancelled?)
03:18muhooand this is what i have spent the night doing. https://www.refheap.com/paste/2989
03:18muhooor rather, HAVING to do :-/
03:18gfrederickslypanov: would a combination of future-done? and future-cancel get you that?
03:19gfredericksmuhoo: I like (fn [k r o n] ...)
03:23gfredericksit's crazy how far I got through that macro before realizing it was emitting cljs
03:26amalloylypanov: future-cancel isn't really a 100% reliable mechanism anyway: once a thread is running, it's hard to interrupt it, if it's not planning/expecting to be stopped
03:27amalloyyou'd be better off putting some code in your worker threads whereby they can check whether someone has requested that they stop
03:29lypanovits blocking on an external process.
03:29lypanovamalloy: would ^ be interrupted or not?
03:30amalloy*shrug*
03:30lypanovah no, in fact i take that back.
03:30amalloyi don't really know the details of the thread-interruption mechanism
03:30lypanovok
03:31amalloyi do know it's changed a few times since JDK 1, because a lot of totally-broken algorithms were used
03:33lypanovhttp://stackoverflow.com/questions/671049/how-do-you-kill-a-thread-in-java
03:33lypanov"See this thread by Sun on why they deprecated Thread.stop()."
03:34lypanovas the page referenced says, .interrupt() will work for the above external process example.
03:34lypanovbut .stop() will almost never work.
03:34lypanovso "putting some code in your worker threads whereby they can check whether someone has requested that they stop" is the suggested path. :)
03:35lypanovthx amalloy!
03:35amalloyyes, i imagine future-cancel uses interrupt, somewhere
03:37lypanovamalloy: yup. it uses interrupt.
03:39calvadosis there a tool to get test coverage reports in jenkins for clojure ?
03:45gfredericksthere's a cljs lib for canvas-y graphics already, isn't there?
03:46lypanovseveral.
03:47gfredericksany pointers? :)
03:47lypanovamalloy: sorry to bug but another question, whats the advantage to futures over agents if cancel doesn't work?
03:48lypanovamalloy: can't i just as well store a "id" in an atom and in my agent task check the id every once in a while to verify if i shouldn't cancel myself?
03:49amalloyagents are supposed to model a value, changing over time. if you never inspect or change that value because the action never returns, what is the point?
03:49amalloyagents also use a different threadpool, and probably have a bit more overhead to keep an action queue and ensure it's updated in a threadsafe way
03:53gfredericksI thought I could use lein-cljsbuild's multi-builds feature to have src code and test code, but doing that in the naive way the two JS files couldn't be combined since they had a lot of overlap; is there a normal way to allow building src and test code separately?
03:56tomojwhy do you want to combine them?
03:57gfredericksthe test code tests the app code
03:57gfredericksso the test code by itself is not very useful
03:57tomojif you compile the test code, the compiled js will include whatever app code is tested
03:57tomojmaybe I don't know what you mean
03:57gfredericksoh -- maybe my mistake was including both main.js _and_ test.js
03:57gfredericksmaybe test.js would've sufficed
03:58tomojjust curious, how are you testing? assert?
03:58gfredericksyeah; I wrote an is and are macro, but yes
03:59tomojcool
03:59gfredericksthe are macro was surprisingly easy :)
03:59tomojI'm testing from tests written in js so far, since I would be too tempted to get sucked into building a test framework (and I want the library to be usable from js..)
04:00tomojexcited to see testing libraries start popping up
04:12sergeyhey
04:15lypanovamalloy: i don't understand what you mean by "because the action never returns"
04:15lypanovamalloy: that would only be the case if it was cancelled. i'd only cancel because a new request arrived and the existing request will use up time if it continues.
04:15lypanovah but then i have another bug.
04:16gfrederickslypanov: you're ignoring the agent's state
04:16lypanovsod it. this is good enough and 3 lines of code.
04:18lypanovgfredericks: not true. the state is the result of the agents work and is what my web action returns.
04:19gfredericksoh okay. Then you're only using it once :)
04:19lypanovnope.
04:19lypanovgfredericks: file watcher -> send-off. request -> await and reply with new state.
04:19lypanovits a compile cache.
04:20gfrederickslypanov: I don't know what anybody's talking about then
04:20lypanovgfredericks: hehe.
04:20lypanovamalloy's comment helped anyway. it make me realize that its just not worth the extra effort to use futures/add cancel logic.
04:21lypanovas agents work by unblocking awaits when the list of pending at the time of the call to await is let go.
04:22lypanovthis means if i press save on a file twice, the first one would be cancelled and get the old state whereas what i really want is for it to wait until the second completes.
04:35Miko2Is there a "deep" variant of transient?
04:43gfrederickstransients of transients?
04:47tomojI see no need for a deep variant
04:51tomojcould you make clojure.zip work with transients?
04:55ro_stso i think i asked this before but i can't find the answer in any of the code i have written already. i have a seq of {modelA_id: … modelB_id: … } and i want to gather that into {(modelA_id's value): [(modelB_id value) (modelB_id value) …]}
04:56ro_stso use A's value as a key for a sequence of all of B's values that map to A in the source map
04:58ro_sti'm guessing that a (for) form will be used here but not sure how to construct it
04:59gfredericksyou want [{:a 2 :b 3} {:a 2 :b 4} {:a 3 :b 10}] => {2 [3 4] 3 [10]}?
04:59ro_stthat's right
04:59gfrederickswell group-by can get you halfway there
04:59borkdudegroup-by
04:59tomojgroup-by always bothers me
05:00gfredericks(into {} (for [[k v] (group-by :a your-maps)] [k (map :b v)]))
05:00tomojif it had a [kf vf coll] version, it would be great
05:00gfrederickstomoj: so that we could (group-by :a :b coll) here?
05:00tomojyeah
05:01gfredericksagrd
05:01tomojreally easy to do..
05:01tomojwould be somewhat surprised if it hadn't been proposed
05:03tomojmaybe it can be fixed in reducers
05:03tomojs/fixed/added/
05:03ro_stor perhaps it could be in clojure 1.5 :)
05:05borkdudepropose it!
05:06tomojso if you (r/group-by identity {:a :b}), should you get {:a :b}, an error,... what?
05:07tomoj(the argument for {:a :b} is that (r/group-by identity {:a :b}) is short for (r/group-by identity identity {:a :b}) and that group-by should cooperate with reduce-kv)
05:09tomojhmm
05:09tomojthat's not right
05:11tomoj(r/reduce (r/group-by (fn [k v] k) (fn [k v] v)) {:a :b}) => {:a :b} ?
05:12tomojer, {:a [:b]} of course
05:14tomojand (into {} (r/group-by ..))
05:14tomoj?
05:16gfrederickswhat was the name of fogus's cljs app?
05:17ejacksonhimera ?
05:17gfredericksah jes
05:17gfredericksyes
05:18gfrederickstotally doesn't start with "mo"
05:19SuperfastJellyfiFetching dependencies with Leiningen seems to be not working from here? Does anyone else have this problem?
05:20ordnungswidrigSuperfastJellyfi: please be more specific
05:22SuperfastJellyfiWe created a list with dependencies in our project.clj file, but at a sudden we got a OverConstrainedVersionException with fetching the dependencies from the remote repositories: central (http://repo1.maven.org/maven2) and clojars (http://clojars.org/repo/)
05:23SuperfastJellyfiand before it was working without a problem
05:23ordnungswidrigwhat did you change?
05:23ordnungswidrigdu you use ranges?
05:24SuperfastJellyfiNothing, even if we create a new project, we get this error.
05:24SuperfastJellyfiOn two different computers.
05:24SuperfastJellyfiWe don't use ranges
05:25borkdudeSuperfastJellyfi hi
05:25borkdudeSuperfastJellyfi what version of leiningen do you use?
05:26borkdudeen please post the project.clj on gist.github.com
05:26SuperfastJellyfiborkdude: 1.7.1
05:28SuperfastJellyfiborkdude: https://gist.github.com/2867410
05:31tomojwhy don't sorted maps of persistentqueues make good priority queues?
05:35borkdudeSuperfastJellyfi it seems that noir 1.2.1 and korma are causing trouble
05:35borkdudeSuperfastJellyfi when I exclude them it works fine
05:37borkdudeSuperfastJellyfi maybe noir 1.21 uses clojure 1.2?
05:38borkdude1.2.1
05:38SuperfastJellyfiborkdude: is 1.2.1 deprecated now?
05:39borkdudeSuperfastJellyfi I guess not
05:39borkdudeSuperfastJellyfi maybe try #leiningen for this
05:40SuperfastJellyfiborkdude: ok thanks for your effort
05:41borkdudeSuperfastJellyfi something seems to depend on clojure 1.2.0
05:42borkdudeSuperfastJellyfi ask this in #leiningen for further info
05:53SuperfastJellyfiborkdude: k thx
06:13almostobsoleteI'm using Clojure in emacs with slime. When reading a source file most of the built functions I can jump to with slide-edit-definition but most libraries (required via project.clj) I can't. I'm guess this is because I don't have the source for those libraries installed. Can I instruct lein to install sources so I can jump to them? would that work?
06:19ggghi
06:22amalloyalmostobsolete: normally that works just fine, as long as you have the libraries in your classpath (normally because you've connected with lein-swank and it's in your project.clj), and you've loaded the code via C-c C-k or something
06:42PKHGHello, who knows about 'round' used in http://www.gettingclojure.com/cookbook:graphics#ascii-bar-chart but clojure gives: java.lang.Exception: Unable to resolve symbol: round in this context
06:45ejacksonPKHG: try Math/round
06:45PKHGthanks will use that one ...
06:46PKHG(replacing) ;-)
07:02magnarsclojure-mode: How do I go about getting emacs into clojure-test-mode automatically after doing clojure-jack-in? It's a bit of a hassle to manually do M-x clojure-test-mode.
07:08bsteuberdoes anyone know how to get rid of the "Failed to collect dependencies for clojure.lang.LazySeq@3eab22f5" in recent lein?
07:08bsteuberhappens with both preview2 and preview6
07:10bb_oz#leave
07:12winkbsteuber: someone in #leiningen posted something like that earlier, care to post your dependencies there as well?
07:20almostobsoleteamalloy_: Thanks! It doesn't seem to work for me though. I'm not loading code with C-c C-k, I just run clojure-jack-in then browse the source files
07:33antares_bsteuber: can you post the entire stack trace?
07:33antares_bsteuber: what OS and JDK do you use?
07:35bsteuberantares: https://gist.github.com/2867852, OSX, Oracle
07:36bsteuberit might be the ssl problem here, though exclusions helped make deps work
07:36bsteuberI just get a compile error now ^^
07:36antares_No versions available for org.clojure:clojure:jar:[1.2.1],[1.3.0] within specified range
07:37antares_so yes, something somehow drags the 1.2.1 requirement
07:37antares_bsteuber: for the Oracle JDK issue (they do not bundle some SSL certificates), see http://architecturalatrocities.com/post/19073788679/fixing-the-trustanchors-problem-when-running-openjdk-7
07:38bsteuberok I'll try, though I never saw the actual SSL message
08:22ro_stthis might be a daft question, but how many concurrent users can a heroku dyno support with, say, a mongodb-backed json rest api?
08:22ro_sttrying to get a handle on when i'd need to add dynos
08:23ro_stalso i'm guessing it's simple to have a ring response gzip its contents
08:24weavejesterro_st: There's some middleware to do that, I believe
08:44Hodappbbloom: problem is, as soon as you start having to introduce features like that, things rapidly get to be an overcomplicated mess...
09:24ro_stanyone running multi-dyno apps on heroku?
09:24ro_sttrying to get a sense of scaling requirements
09:52gfredericksIs there any reason core.logic couldn't have a condr that tries the clauses in a random order?
09:54dnolengfredericks: probably not, and for what purpose?
09:55gfredericksdnolen: if I'm interested in getting a random match, it would be faster than (rand-nth (run 10000 [q] ...))
09:58dnolengfredericks: you could write a goal that takes a vector of goals and tries a random one.
10:01gfredericksdnolen: that's a good idea; thanks
10:13jweissany emacs users know how to get a different repl buffer for each project you're working on? I use clojure-jack-in, it asks if i want to kill the existing process, if i say no, it just switches the existing slime repl to the new project.
10:17tmciverjweiss: I just use separate emacs instances.
10:18jweisstmciver: doing 'lein swank' from cmdline and then slime-connect does give me 2 separate buffers
10:18jweissi am not sure why clojure-jack-in doesn't just do the right thing
10:32si14hey, guys. anyone using ClojureScript with emacs here? Is there anything better than "inferior lisp" for browser REPL?
10:50ro_stany one running clojure web apps in production on heroku? what sort of reqs/sec are you getting per dyno?
10:51dnolensi14: not yet
10:52si14dnolen: are there any plans for it?
10:52dnolensi14: even then to get full good-ness someone needs to design and write some kind of reflection API
10:52si14dnolen: ah, you're right
10:52dnolensi14: plans ... as in we'd like for someone to do it.
10:52si14dnolen: yeah, I see :)
10:53si14dnolen: btw, I should say you "thank you" for your work at ClojureScript :)
10:54si14it's awesome. has some issues here and there, but still awesome
10:54dnolensi14: thx! there's tons to do as far as CLJS goes, so these are just a matter of time. personally focusing on source maps and data struture perf.
10:54dnolenat the moment
10:54ro_stsource maps: woohoo
10:54ro_stfor use with the new chrome dev tools?
10:55si14dnolen: nice to know.
10:56dnolenro_st: yes
10:56ro_stawesome!
11:30solussdis it possible to add a 'class method' to a record via a protocol ?
11:31ezyangI'm getting null pointer exceptions from PersistentTreeMap, and I'm wondering if there are any invariants that I should know about but don't.
11:31TimMcsolussd: Pretty sure there's no mechanism for class methods except via gen-class, and that might not count.
11:32TimMcezyang: Maybe it doesn't accept null keys or values?
11:32TimMc&(assoc (clojure.lang.PersistentTreeMap.) :a nil) ;; no, that's fine
11:32lazybot⇒ {:a nil}
11:33TimMcCan you make a reduced testcase?
12:52ezyangTimMc: Working on it.
12:55ezyangTimMc: Here we go: http://hpaste.org/69503
13:03ezyangSomewhat relatedly, if I want to work on Clojure's JVM classes, do I load it into Eclipse?
13:05dnolenezyang: you can just add the clojure.jar to your project if you're using a Java IDE
13:06ezyangHmm, but that is a bit annoying because Eclipse doesn't understand how to get out sources.
13:06dnolenezyang: you want the sources for reference?
13:07ezyangMostly for debugging actually (see the error I pasted above)
13:08ezyangI'm sure I'm trampling over some Clojure invariant (because obviously tree maps work in real Clojure apps) but I don't know what.
13:08ezyangMy current conjecture is that Clojure assumes that static initializers are loaded in a specific frder.
13:12dnolenezyang: should probably ask on the ML
13:12ezyangOK. The general one or the dev one?
13:12dnolenezyang: general one
13:14TimMcezyang: That's pretty weird. I don't see what could be wrong.
13:25ezyangposted
13:33ezyangWell, I found a workaround.
13:34ezyangAlso, the Clojure list hates my emails :-(
13:34ezyangIt took four days for my last message to show up.
13:35bsteuberthe cljs compiler used in cljsbuild 0.2.1 seems to rename throw() in advanced compilation
13:35twhumeI'm doing something evil and unusual, and I could do with some help. I want to create, briefly use, and then dispose of a large number of Classes (literally millions). I create the class in the "let" of a function, and it is never returned; so I'd expect it to be garbage-collected, but it isn't being. After about 57,000 classes are created, I get an OutOfMemoryError. Any ideas? Code at http://pastebin.com/Z3Kk0Yu0
13:37bsteuberoh nevermind, thought the rename is part of my problem, but it isn't..
13:38borkdudetwhume have you tried dorun?
13:38twhumeborkdude: do you mean instead of doall in the final line?
13:39borkdudetwhume doall retains the head, so all the classes will be in memory the same time
13:39twhumeaha… will give that a go now.
13:39twhumeNope, falls over at the same point.
13:40raekhuh, did github just start using https instead of ssh by default?
13:41twhumeborkdude: and would they all be held in memory anyway? They're created in that test-class function and never used outside it - so I would expect them to be GCd (or available for GCing) when it's done...
13:41borkdudetwhume good point
13:42borkdudetwhume what does get-class do?
13:43twhumeit uses DynamicClassLoader to load a class from a byte array of Java byte code (using ClassLoader.defineClass)
13:43dnolenezyang: some bugs around ML approval, should work after the first approval.
13:43twhume…and returns the class thus loaded.
13:43borkdudetwhume maybe references to the returned class are retained elsewhere? else I don't know
13:44twhumeYep, I'm guessing that something somewhere is keeping them, otherwise the JVM would GC - but I can't tell what that would be, and how I tell it not to...
13:46twhumeI've tried forcing a GC after every thousand loads (so there are 57 GCs being requested before it falls over), but that doesn't help… I'm a bit stumped, and not sure where to look.
13:46borkdudetwhume I would look in the get-class function
13:46dnolentwhume: have you tried that code in pure Java?
13:46TimMcI *think* OOM is guaranteed to only happen if GC doesn't help.
13:46twhumednolen: no, that sounds like a good next step, doesn't it?
13:46dnolentwhume: yep
13:47twhumeI'll give it a go now.
13:47S11001001doesn't necessarily mean that gc has to run to find an OOM
13:49TimMcWait, I'm thinking of SoftReference or something.
13:49TimMctwhume: Is this that thing where you are generating all possible classes?
13:50twhumeTimMc: yep, that's it.
13:55twhumeHmm, in pure Java I can go to 100,000 classes loaded without trouble. So this looks Clojure-specific.
13:55twhumes/go to/generate/
13:57dnolentwhume: what does you code look like w/o the doall? did you try dotimes?
13:58patrkrishi folks. viewing the cheatsheet on clojure.org, it seems that you're supposed to call the method .indexOf to find the index of an element in a vector. can this really be true?
13:58twhumednolen: I've not tried dotimes, no. W/o the doall, it's as in http://pastebin.com/Z3Kk0Yu0 but with doall replaced by dorun.
13:59technomancypatrkris: I think it's a subtle hint that a vector may not be the data structure you're looking for if you want that
13:59patrkrisah
14:00patrkristechnomancy: i'm using a vector to define a sort order of a set of items. do you have any suggestion to do something else?
14:00dnolentwhume: try dotimes, your code is just side effects, range and dorun/all not necessary
14:01nDuffpatrkris: a map tracking object->index would make more sense in that case, being O(1) lookup.
14:01nDuffpatrkris: ...a vector being O(n) to search through makes it very much not the right tool for the job.
14:02patrkrisnDuff: yes, I thought about that, but had the idea that a vector is a little more succinct, and since there aren't many items, it shouldn't take long
14:02patrkrisbut I think I'll walk the map road
14:02technomancyif you know it's never going to get big, .indexOf is fine
14:02twhumeSorry, was bounced out.
14:02twhumedotimes displays the same behaviour - falling over after 57,000 or so classes loaded.
14:02mebaran151patrkris: by the way for very tiny maps, Clojure does an optimization, using an ArrayMap instead
14:03patrkriscoolio
14:03mebaran151which probably works very similarly in terms of algorithm to indexOf
14:03nDufftwhume: is this PermGen space or heap that you're exhausting?
14:03twhumePermGen
14:03nDuffahh.
14:04nDuff...yeah, then; permgen space isn't typically garbage collected. Which arguments are you starting your JVM with?
14:04nDuff(and which JVM release is it?)
14:05nDufftwhume: ...also, have you set -XX:MaxPermGenSize to give yourself more breathing room?
14:05twhumenDuff: I think it's java version "1.6.0_31" (on mac), I'm working in Eclipse and CounterClockwise is launching the REPL for me so I'm not 100%.
14:06twhumenDuff: I can do that, but in future I'd like to be loading literally millions of classes… upping MaxPermGenSize might help me do more, but there seems to be an underlying issue with Clojure here (given that I can do what I want in straight Java, but not in Clojure)?
14:06dnolentwhume: did you try loading a million classes in Java?
14:07twhumednolen: I tried loading 100,000 and it worked fine. Clojure repeatedly falls over at 57,000. I'll do a test with a million in Java now...
14:07nDufftwhume: I don't accept that premise, actually -- loading a million classes without enough permgen shouldn't be possible in Java either.
14:07nDufftwhume: ...that said, Clojure _does_ use more permgen space, to be sure, as it generates lots of little classes as a matter of course.
14:07dnolentwhume: one possible difference is that Clojure itself loads up a class per fn
14:08twhume…OK, that might explain a slightly higher limit for Java. Doing a test with 1m now.
14:08nDufftwhume: I'd suggest using jmap + jhat to look for situations that might be preventing GC, by the way.
14:09nDufftwhume: see http://frankkieviet.blogspot.ca/2006/10/how-to-fix-dreaded-permgen-space.html
14:09twhumethanks!
14:11nDuff(by the way, one place where I _do_ get permgen leaks, and am Very Not Happy about it, is the Clojure runtime not being fully unloadable -- tends to lead remnants in thread-local space, such that unloading and reloading plugins written in Clojure can result in duplicate copies of clojure.* classes accumulating, each tied to a new, plugin-specific classloader instance)
14:11twhumeOK, I've just managed to generate and load 1m classes from a pure Java version on the same machine; so I don't think the issue is overhead of Clojure, I think something is keeping those generated classes hanging around...
14:12nDuff...well, jmap+jhat are your friends.
14:12gtraktwhume: how big are those classes relative to your permgen and whatever's loaded up by clojure startup?
14:12twhumeI also notice that in Java, I can repeatedly regenerate and reload the same class name. On Clojure I get a ClassLoader error unless I rename the classes each time I generate them.
14:13twhumegtrak: the classes are minimal, containing a 2-opcode identity method and nothing else.
14:14nDufftwhume: ...eh? Sounds like you're doing something interesting, then.
14:14gtrakI wonder if the extra runtime classes would make a big hit, then... if you increase permgen and the gap gets smaller you would know
14:15twhumenduff: exhaustive search of possible programs, to find non-intuitive optimal ones (it's called a superoptimiser - not my term - http://en.wikipedia.org/wiki/Superoptimization )
14:15nDufftwhume: meant interesting in terms of your implementation, to trigger those behaviors.
14:15twhumegtrak: possibly, I'll give that a go and see
14:15hiredmantwhume: are you loading the classes in both cases (the java and the clojure case)?
14:16dnolentwhume: so in the Java code are those classes getting GCed right away?
14:16hiredmantwhume: how are you loading it in the java case? still using dynamicclassloader?
14:16twhumehiredman: hmm. Am definitely loading them in the Java case (and invoking a method). In the Clojure case I'm creating and loading them but not using them (in my test code exercising this problem: in the real thing I load and invoke them).
14:16twhumednolen: yes, looks that way.
14:16hiredmantwhume: what is the parent classloader in both cases?
14:16mebaran151hey all, what's the best way in clojure to fetch all the elements from an xml document by tag; the output from clojure.xml/parse seems a little raw for that
14:17sridother than one and pinot, are there any new clojurescript frameworks of late?
14:17hiredmantwhume: how are you loading them in the java case?
14:17twhumehiredman: in Java I've written a class which extends ClassLoader and calls defineClass(). In Clojure I'm using the DynamicClassLoader.
14:17hiredmantwhume: have you looked at the source of dynamicclassloder?
14:18twhumehiredman: had a quick look, it seemed straightforward. I think that's next (after playing w/permgen settings).
14:18twhumeFolks, thanks for all your help. I have to head off now but will look into your suggestions (and those links, nDuff). Will probably be back here tomorrow :-$
14:19hiredmanI find it hard to believe someone could look at the source and still ask about dynamicclassloader keeping a reference
14:22rlbIf you wanted to dump a large number of random integers (as text) to a file as quickly as possible, is a tail recursion and .write probably the best way?
14:23rlb(just toying with a conversion of someone's trival perf test)
14:25nDuffrlb: ...for microbenchmarks, details matter (so what kind of structure those random numbers are stored in, for instance, matters)... but generally, yes-ish. Might want a buffered writer.
14:27rlbthey're generated via (rand-int MAX)
14:27jweissis there any way to refer to "this" in a record? eg, (defrecord myrec [a b]) (myrec. {:foo (:bar this)} :baz)
14:28jweissthat's a bad example, but the point is i want to pass in a literal as one of the args to the constructor, and inside there be able to refer to the overall object
14:29dnolenjweiss: you could do it via an atom or a mutable field - neither recommended.
14:29magnarsemacs clojure-mode: any way to jump into clojure-test-mode after a clojure-jack-in more conveniently than M-: (require 'clojure-test-mode) M-x clojure-test-mode ?
14:31technomancymagnars: if you install clojure-test-mode the right way it will be activated automatically when you jack in.
14:31technomancyusing package.el will set up the autoloads for you
14:31technomancyotherwise put the require in your init.el
14:32magnarstechnomancy: oh, that is excellent. putting the require in init.el didn't work out for me, but I'll give package-install a go. Many thanks.
14:34bbloomdnolen: i noticed that code blocks inside expressions are implemented via (function(){…})() instead of the comma operator. is that something gclosure reliably optimizes?
14:34dnolenbbloom: yes
14:35bbloomdnolen: cool. that makes things eaiser
14:35dnolenbbloom: though you do have to careful in some cases - one rule of thumb, if a fn doesn't get unwrapped at :simple - it won't get unwrapped.
14:35bbloomdnolen: I was mostly looking at emit-block
14:36magnarstechnomancy: as for just popping (require 'clojure-test-mode) into init.el, it gives me this: (file-error "Cannot open load file" "slime") unless I have an open slime-repl
14:36bbloomdnolen: in particular, emit :do
14:37technomancymagnars: oh I guess that makes sense. you can put it in (eval-after-load 'slime '(require 'clojure-mode.el))
14:37technomancybut handling all this stuff for you is what package.el is good at
14:38dnolenbbloom: it's pretty much always done in expression contexts because of JS rules about where expressions can go.
14:40bbloomdnolen: yeah, a simple search for ")()" shows that. I was just wondering if there would be any benefit to using parens and the comma operator, but if gclosure optimizes it, then it's all good
14:42dnolenbbloom: parens is not enough in many cases far as I know.
14:43bbloomdnolen: i'd believe that, but i can't think of any off the top of my head. which cases?
14:43dnolenif(... complex test ) { ... }
14:44bbloomif ((console.log("x"), true)) console.log("y");
14:44bbloomthat seems to work in node
14:44dnolenbbloom: it's not enough, you need to consider how complex the test might be
14:44dnolen(if (let [x (or ...)] ...) ...)
14:46magnarstechnomancy: deleted my clojure-mode in site-lisp/ and installed with package.el - it's required fine, but still have to do M-x clojure-test-mode to activate after jacking in.
14:47dnolenbbloom: (if (some-macro ...)) is another one, satisfies? is a pretty complex one that actually appears in core.cljs
14:48technomancymagnars: it should loop over open clojure-mode buffers and apply it if it detects that they're tests
14:48rlba loop calling (rand-int MAX) appears to be much faster than one calling (.nextInt rng MAX)
14:49rlb(or I'm doing something wrong...)
14:49technomancymeaning if the namespace includes the string "test"
14:49neotykrlb: consider using channels, you will spend most time in I/O
14:50neotykrlb: http://docs.oracle.com/javase/6/docs/api/java/io/FileOutputStream.html#getChannel()
14:51magnarstechnomancy: yes, you're right. I assumed it would put all clojure-mode buffers into clojure-test-mode. Sorry for the confusion. It works nicely installed from package. Thanks again for the help.
14:51bbloomdnolen: just experimenting w/ the compiler & a js repl. i realize why let needs the wrapper function, but i'm not convinced about all blocks
14:51technomancycool
14:52bbloomdnolen: basically, anywhere we *emit* a javascript *statement* we need the )() wrapper -- but you wind up with double wrappers in a bunch of cases
14:52technomancyhas anyone gotten postgres hstore working with jdbc?
14:53neotykdnolen: have I seen somewhere ticket for multiple browser repls running from one process?
14:56neotykdnolen: can't find it in jira, though vaguely remember it been mentioned somewhere
15:00dnolenbbloom: blocks might appear in as test expressions
15:01bbloomdnolen: ok, well i'm going to experiment & i'll let you know if i think there are any gains to be had by thinking about this more deeply
15:01Miko2Hmm-m.
15:02Miko2I'm getting quite weird behaviour with transient maps.
15:02Miko2https://gist.github.com/2870176
15:02dnolenbbloom: it's not an avenue I think that is worth pursuing - GClosure gets rid of it. Best to look at what happens during :simple to see what I mean.
15:03dnolenneotyk: I recall a ticket - definitely a branch on GitHub
15:03bbloomdnolen: yeah, i don't expect to find any potential gains. i'm just trying to understand gclosure's behavior better
15:04Miko2For the first 8 conj!'s it uses TransientArrayMap, but for the nineth it conjs to TransientHashMap
15:04dnolenbbloom: from what I can tell - unwrapping happens during :simple, inlining during :advanced
15:05bbloomdnolen: yeah, simple seems to do constant folding
15:06bbloomgclosure really is an impressive little optimizer :-P
15:06gtrakMiko2: if you look on the docs, you'll notice it says they're not supposed to be bashed in place
15:06TimMcMiko2: THat's expected.
15:07rlbneotyk: thanks, though that wouldn't explain the large difference between rand-int and .nextInt. With rand-int, clojure's about half the speed of the java program (which is better than all the competitors except c++).
15:07dnolenbbloom: it is, in the early days I didn't observe a big perf difference between :advanced and other optimization modes. Now that we produce much more optimal JS, the perf difference is quite large.
15:07rlbanyway, no big deal -- I was just toying with it.
15:07Miko2TimMc: I didn't expect that...
15:08gtrakMiko2: "You must capture and use the return value in the next call. In this way, they support the same code structure as the functional persistent code they replace."
15:09bbloomdnolen: yeah, but when your metaprogramming happens on startup (instead of during compilation) like ruby or raw javascript does, the restrictions advanced mode places on you can be a drag
15:09Miko2Oh, hmmm. Well, that explains it.
15:09Miko2Thanks. Have to change the code. :)
15:09gtraknp
15:10gfrederickswhat's the goodest canvas lib for cljs?
15:10dnolenbbloom: not IME since the kind of metaprogramming you can do in CLJS is not even possible in those languages.
15:12bbloomdnolen: of course, cljs definitely is a better trade off. you generate more code, compress it better w/ gclosure. rather than spend an extra 2 ms stitching strings, you spend an extra 1.5ms downloading bits. im just saying that if you're writing wrap js, like this large coffeescript project i have, then i opted to ignore advanced compilation mode b/c i wanted to be able to compose method names from strings and look them up at runtime
15:12bbloomwrap -> raw
15:13PhearTheCealAll right, I'm downloading Clojure. I've never used a functional language before. And advice for me right now?
15:13gfredericksdon't download clojure, download lein
15:13PhearTheCealtoo late
15:13bbloombetter yet, don't download anything at all and try your hand at http://www.4clojure.com/
15:13gfredericksabort abort
15:14PhearTheCealbbloom: Awesome! Thanks
15:14RaynesYou really do need to download lein though.
15:14gfredericksno way. 4clojure.com is turing complete.
15:15RaynesDownloading Clojure is trying to drive an engine.
15:15cgagyeah definitely get lein
15:16cgagi remember trying to get into clojure before lein was out, or atleast before i knew about it and it was hugely discouraging
15:16dnolenbbloom: JS devs do that because that's all the JS metaprogramming you can do & GClosure doesn't make JS programming any nicer - in fact it just makes it more tedious.
15:19bbloomdnolen: that's exactly what i'm saying :-)
15:20bbloomPhearTheCeal: make sure you follow a couple of the top ranked people, so you can learn alternative approaches!
15:20PhearTheCealbbloom: Like who?
15:21philr /quit
15:21dnolenbbloom: heh, yes
15:22PhearTheCealbbloom: How do I see their solutions?
15:22bbloomPhearTheCeal: you need to solve the puzzles on your own first ;-)
15:23PhearTheCealbbloom: makes sense :P
15:28PhearTheCeali'm on problem 4
15:28PhearTheCeal(= (list __) '(:a :b :c))
15:28PhearTheCealI think I need to learn about syntax
15:30AimHerePhearTheCeal, syntax is mostly straightforward; all your code is in the form of a list (command arg1 arg2 arg3 ...). Most things that don't look like that are just syntactic sugar for something that does
15:30AimHere'(1 2 3) is sugar for (quote 1 2 3) for instance
15:30gfredericksmmm, tasty
15:30AimHere,(doc list)
15:31AimHere&(doc list)
15:31lazybot⇒ "([& items]); Creates a new list containing the items."
15:31gfredericksthe & there means that list takes multiple arguments
15:32AimHere&(list 'item1 'item2 'item3 'item4)
15:32lazybot⇒ (item1 item2 item3 item4)
15:33gfredericks&(list :item1 "item2" #{'item3} [::item4])
15:33lazybot⇒ (:item1 "item2" #{item3} [:clojure.core/item4])
15:33PhearTheCealI can't put an &
15:33gfredericksyou don't need to
15:33PhearTheCealso the answer is ":a" ":b" ":c" ?
15:34gfredericksshouldn't be
15:34groovemonkeyalmost. They're not strings.
15:34AimHere&(list ":a" ":b" ":c")
15:34lazybot⇒ (":a" ":b" ":c")
15:34gfredericks:foo is a keyword
15:34AimHerekeywords are a special kind of data in clojure
15:35PhearTheCealoh...
15:35PhearTheCealLike variables?
15:35gfrederickscloser to strings and numbers
15:35AimHereSortof, but they don't hold a value except themselves
15:35bbloomstrings, symbols, and keywords are different things! :-)
15:36bbloomvar s = "foo"; // var-keyword s-symbol =-keyword foo-string
15:36amalloykeywords are a lot like "strings that are only ever used to compare for equality"
15:36gfredericksthat's the only thing I've ever said that amalloy liked
15:36amalloygfredericks: and there's a second one!
15:37gfrederickskilling it!
15:37AimHereI thought of keywords more as those symbols in SICP that you didn't need to bind any actual value to
15:38gfrederickskeywords are like enums except you don't get typo-checking
15:39gfredericksthat's why _real_ clojure programmers always (def foo :foo) at the top of their namespaces
15:39PhearTheCealso var and = are keywords, but you can define your own keywords. And keywords are like strings?
15:39gfredericksoh man
15:39AimHereNo, var and = are symbols
15:40AimHereThey are bound to values, which in those cases are functions
15:40AimHereUnless var is a macro that is
15:40gfredericksI think he read too much into bloom's last statement
15:40AimHerekeywords are always denoted by the preceding colon
15:42amalloyi think bbloom's last statement was either confusing or nonsense, so that's fair, gfredericks
15:42bbloomgfredericks: sorry, was just trying to point out that strings, symbols, and keywords are different things.
15:42gfredericksinvoking javascript was an odd way to do that
15:44gfredericksactually it might make sense using the javascript definition of "keyword" which would be quite misleading
15:44bbloomgfredericks: *shrug* makes sense in my head :-P
15:45nDuffI'm trying to AOT-compile some code which involves setting namespace-global variables with the results of calls which will be available at runtime but don't work yet at compile-time. What's the appropriate way to make this work?
15:45amalloyhide everything behind delays
15:46borkdudewhat is the easiest way to open a file from the console in osx in Emacs.app (when it is not running it should start automaticall and it should work with files that don't exist, i.e. "emacs foo.txt" )
15:46gfredericksyou can hide the delay behind a function so that you only have to remember it's a delay in one place
15:46borkdudeI've tried several approaches now but they all suck
15:46gfredericks(let [foo' (delay (make-foo))] (defn foo [] @foo'))
15:46nDuffThe thing that bugs me here is that some of these are called somewhat frequently, so adding extra indirection is kinda' unfortunate.
15:47gfredericksnDuff: you could make a macro that does that ^ if you hate doing that
15:47gfredericksunless you just hate calling it as a function
15:48gfredericksin which case there's no way around it unless you want to utilize pure evil
15:48nDuffHmm. At least the functions could definitely be type-hinted; I'm not sure if the delays can...
15:48PhearTheCealdang it.... 4clojure is down
15:48S11001001nDuff: switch on whatever the compiling var is in clojure.core
15:49amalloywhoever runs that website needs to get their shit together
15:49amalloy(it's back up now, PhearTheCeal)
15:49S11001001nDuff: runtime code will thus be compiled but not run at compile time. Compile-only path will be compiled in, but that's no big deal. Then just make sure you don't use compilation to load when runtime is real
15:52S11001001if you compile and what you're compiling recursively loads something that's already compiled, the compiling flag is still on
15:52S11001001so you're overloading the compiling flag to mean "I don't have that function I need"
15:53S11001001accordingly, if you use compile to load when you do have that function, then you're telling your code that you don't have the function
15:54S11001001this is the sort of thing you have to keep in mind if you want to make module loading do different things depending on environment
16:00amalloynDuff: you're causing yourself a lot of pain to avoid just using some delays. the cost of deref'ing a delay is extremely small; it's smaller than the cost of calling a function
16:01amalloyor i guess it's exactly the cost of calling a function, since you have to call clojure.core/deref
16:01SgeoBesides no tail-call optimization, what concessions to the JVM and to interoperability with Java code does Clojure make?
16:01S11001001amalloy: where does the lock go?
16:03amalloyS11001001: the synchronize block doesn't go away. but again that's small
16:03ivanSgeo: perhaps having both nil and false
16:03S11001001Sgeo: + is weird
16:04SgeoS11001001, how so?
16:04dnolenSgeo: JVM error handling, no continuations
16:06S11001001Sgeo: won't autopromote bytes, shorts, ints, longs beyond long; same for - and *, and I think inc/dec
16:06borkdudeis defstruct a bit deprecated or how was it again?
16:06dnolenborkdude: deprecated
16:09nDuff(def ^some.java.Class (delay ...)) doesn't seem to result in the compiler being aware of what type dereffing the delay will result in.
16:09technomancySgeo: the biggest concession to the JVM I've noticed beyond needing primitives for speed is probably the inability to treat arbitrary data types as functions
16:10llasramAnd you could hide *that* behind a symbol-macrolet!
16:11mebaran151is there any easy stdlib function to convert a Java XML Element to a nice clojure hashmap?
16:13dnolenmebaran151: https://github.com/clojure/data.xml ?
16:14borkdudednolen is this the same as clojure.xml?
16:14borkdudednolen or an addition
16:15mebaran151dnolen: I already have some nodes returned unfortunately (would be great if I had a handle on a string representation)
16:15dnolenborkdude: I don't know what clojure.xml is
16:16borkdudednolen https://github.com/clojure/clojure/blob/master/src/clj/clojure/xml.clj
16:16mebaran151borkdude: I think clojure.data.xml is the new clojure.contrib.lazy-xml
16:16amalloydnolen: the awful/broken namespace in clojure
16:16borkdudeit's obviously not the same then
16:16mebaran151like wise if anybody had a nice clean solution for getting all the tags by tag name in pure clojure, I'd also be much obliged (the internet is rife with examples that rely on clojure.contrib.zip-filter, which seems deprecated)
16:16hiredmanclojurebot: ping
16:16clojurebotPONG!
16:17hiredman,*clojure-version*
16:17clojurebot{:interim true, :major 1, :minor 4, :incremental 0, :qualifier "master"}
16:18borkdudemebaran151 I think the parse function in clojure.xml turns xml into nested maps
16:18mebaran151it'll take an xml string, but the problem is I have a bunch of xml nodes; it looks like they wrapped that function into the parser unfortunately
16:19solussdanyone here using the swiss-arows library? just discovered that the diamond one doesn't work inside a macro (backtick)
16:23raekwhat testing frameworks should one checkout these days? (I'm currently using Midje.)
16:23mebaran151borkdude: I probably could get clojure.walk to do what I want actually
16:24mebaran151though I don't know if there's a way to teach it how to make a node a seq
16:25borkdudehmm, there was a discussion here on group-by being sucky if you want to select things based on a function
16:25borkdudethere's an example of what was suggested in that discussion on page 119 of Clojurebook
16:25borkdude:)
16:25borkdude(called reduce-by)
16:29mprokosI am trying to get a repl to run in my lein project. I just run clojure.main/repl from (defn -main) but it just prints a prompt and returns.
16:29mprokosI am using clojure 1.4.0
16:30technomancyyou need trampoline for that
16:31technomancylein trampoline run -m clojure.main/repl
16:35mprokosAwww.. I see
16:37bbloomdnolen: weird. can't use extend-type on RegExp because gclosure will disable optimizations on regexs related to functions with known side effects
16:38dnolenbbloom: yep, that's mentioned on the RegExp tickets
16:39bbloomdnolen: i implemented IPrintable, but it doesnt work in advanced mode :-(
16:39bbloomah, i see your note in CLJS-68
16:40dnolenbbloom: if RegExp extension is going to work it must be done by adding a new native type to the list - those types which should never be modified directly via prototype
16:41bbloomdnolen: i assume that list exists now, for objects? where is that list?
16:41dnolenbbloom: in the macros file
16:42bbloomdnolen: ah, core/base-type, got it
16:43dnolenbbloom: and actually it won't work typeof on RegExp -> 'object'
16:43bbloomdnolen: ok, i haven't ventured into this code path yet. give me a moment to make sense of it
16:43bbloomdnolen: heh, oh, actually i did. sorta, for the apply/call/arity stuff -- amazing how much logic is packed into so little space!
16:51borkdudehas anyone got a good example of how to use reduce-kv? I want to see if it is similar to what we were looking for in the discussion (and reduce-by in clojurebook), so that it in fact already existed all along
17:00gfredericks&(doc reduce-kv)
17:00lazybot⇒ "([f init coll]); Reduces an associative collection. f should be a function of 3 arguments. Returns the result of applying f to init, the first key and the first value in coll, then applying f to that result and the 2nd key and value, etc. If coll contains no en... https://www.refheap.com/paste/2994
17:02gfredericks,(reduce + 0 [1 2 3 4])
17:02clojurebot10
17:02muhoohaving brain-lock. what's the mor idiomatic version of this: ##(reduce #(or %1 %2) [true false false])
17:02lazybot⇒ true
17:02gfredericksthere couldn't be a more natural example than that
17:02technomancymuhoo: some identity maybe?
17:02gfrederickstechnomancy: you can pass a monad to some?
17:03technomancyyou can pass anything to some!
17:03cmajor7most of my experience is backend (some years). now I'd really like to get into front end (noir + clojurescript + twitter bootstrap). what is the best/fastest way to start? screencasts/posts/docs, etc.. looking at noir docs, twitter bootstrap examples, some hiccup docs. looked at some posts (e.g. http://bit.ly/Lt0Qwt ), played with noir-bootstrap (http://bit.ly/Lt10Uo), but still feel a little detached from where to start
17:03muhoothat'll work
17:10borkdudeI guess I can't use reduce-kv for this
17:11borkdude(for the same group-by using a fn selector)
17:11borkdudesame as
17:31TimMcmuhoo: Is the input collection the result of mapping a predicate over something?
17:33technomancyseancorf`: do you know what it would take to add hstore support to c.j.jdbc?
17:33technomancyor even if that's the appropriate place for it?
17:37bbloomdnolen: ok, i think i have a good understanding of protocols in cljs now
17:37dnolenbbloom: cool
17:38bbloomdnolen: looking at the implementation of goog/typeOf -- that's a bit of a scary function to call on every protocol dispatch against native objects
17:38dnolenbbloom: I don't see how we could do any better.
17:39bbloomdnolen: yeah, i'm not sure yet… still thinking about it.
17:40dnolenbbloom: and even that is faster than messing w/ native prototypes. V8 punishes you for adding things to String & Array etc. directly.
17:40dnolenbbloom: and my impression so far has been so does SM & JSC
17:40bbloomdnolen: makes sense to me -- don't want to change those thing's prototypes anyway, especially not object, so you at least need a solution for that, might as well reuse it for strings, arrays, etc
17:40dnolenbbloom: so what we have performs well enough for native types.
17:44bbloomdnolen: what about obj.constructor.toString() as keys instead of goog.typeOf ?
17:45dnolenbbloom: you'd have 1) show that it's not slower, 2) that it works in every JS environment we care about going back to IE6
17:46bbloomdnolen: IE6? seriously? *cry* ok
17:49dnolenbbloom: it's not worth spending too much time on IMO. what we have works - the current perf is acceptable for natives - and the Clojure stuff just zips along.
17:51dnolenbbloom: the one place where we do directly extend a native - String - is a large source of pain.
17:51bbloomdnolen: i'm exploring this so i can better understand why things are done the way they are done -- that's just how i work
17:51bbloomdnolen: pain == slowness?
17:52dnolenbbloom: yes
17:52bbloomdnolen: via protocols or something else?
17:52dnolenbbloom: no directly, we extend String so that keywords can be functions. it's very slow. I put in a temporary fix for the most common case (:foo x)
17:53bbloomdnolen: slow b/c it disables some of V8's optimizations?
17:53dnolenbbloom: disables everyones optimizations
17:53bbloomdnolen: heh, fair enough -- dopey javascript. such an almost beautiful little language :-)
17:53quizmeis it possible to compile clojurescript in clojurescript ?
17:54bbloomquizme: no, the clojurescript compiler is written in clojure
17:54dnolenbbloom: it's actually faster to to construct an object (Keyword) at the call site and invoke on that.
17:55bbloomdnolen: hm, interesting. and if you replace all keywords with objects with a single string field, what gets slow then?
17:56bbloomdnolen: alternatively, every new keyword could effectively be a "leak" like symbols in matz's ruby. basically store keywords as integers instead of strings and have an array of every keyword ever seen
18:01dnolenbbloom: allocations are not free, I assume strings are optimized by JS engines.
18:02dnolenbbloom: CLJS programs have the advantage of being whole program optimized. We could preallocate all the known keywords ahead of time under advanced compilation. And fall back on the slower thing for unknown runtime keywords (from read-string say).
18:03bbloomdnolen: that's an interesting idea! because known keywords can be compiled to an integer lookup, which is mega fast -- no allocations
18:04dnolenbbloom: integer lookup could be interesting, but we already have string hash code caching in master.
18:05dnolenbbloom: pre allocated keywords could be constructed with their hash codes, at that point I don't think property access will be the bottle neck in any program.
18:06bbloomdnolen: why bother with hash codes? why not just compile :foo to known_keywords["?:foo"] where ? is that special char
18:07dnolenbbloom: because we have complex keys.
18:07bbloomdnolen: not in the set of known keywords!
18:07dnolenbbloom: we still need to call hash on the number. how do we know that's not a real number?
18:08dnolenwe can't extend prototype on Number meaning -hash on Number will be slow, etc.
18:08bbloomdnolen: what number? let's back up a step
18:09dnolenbbloom: when looking up a key we generally always call hash on the key, since the key can be anything.
18:11bbloomdnolen: i think this all makes sense in my head, let me write up some notes & link you too them. irc is hard to get a broader idea across
18:13dnolenbbloom: sure though, I also suggest you take a closer look at how maps and hash currently work.
18:14bbloomdnolen: yeah, i looked at those a bunch. the thing is i don't think it matters. we don't need to use a map or hash, just a js object or array.
18:15dnolenbbloom: js object or array for what?
18:15bbloomdnolen: typing up notes :-)
18:22gtrakis instance? on a record supposed to work?
18:22gtrakdoesn't seem to work
18:27gtrakmight be freaking AOT
18:27rcghttps://github.com/ruedigergad/cljNetPcap
18:27rcghttps://github.com/ruedigergad/cljAcmeUtils
18:28rcgjust in case you are interested or this is helpful
18:28rcgthe first one is a wrapper/facade/whatever for using jNetPcap from withing clojure
18:29rcgthe latter is just a bunch of helper functions i came up with over time and found quite useful
18:29rcgi just finally had the time and took the chance to put this stuff online
18:29dnolengtrak: it does, but you have to watch out for redefinition
18:30gtrakdnolen: I think that's the culprit
18:35bbloomdnolen: sorry, got distracted by phone call. look at: https://www.refheap.com/paste/2995
19:08gtrakhmm, i would have expected slurp and spit to use IOFactory on the arg, seems strange
19:09gtrakthey kinda do the same thing
19:09clojurebottwo things are more than one thing
19:11gtrakI suppose IOFactory came after protocols, after slurp/spit
19:12TimMcslurp and spit are *ancient*
19:14gtrakwait, they call jio/reader
19:14gtrakso I can use make-reader
19:14gtrakduh
19:19gtrakfreaking great :D
19:24sridhow do i access `this` in clojurescript from event handlers? this question was asked before <http://osdir.com/ml/clojure/2011-08/msg00558.html&gt; but without a response
19:25pbostromsrid: (this-as x (do-something-with x))
19:26velviaHi guys, newbie here, really like Clojure so far
19:27velviaLeiningen question. If I have a project with mixed Java and Clj, and I do "lein compile" will it detect and recompile changed Java files too?
19:27velviaI'm using 1.6.x and it doesn't seem to detect Java file changes
19:27sridpbostrom: thanks! looks like cljs is not fully documented yet.
19:28technomancyvelvia: you have to tell it where the java files are kept; set :java-source-path in project.clj IIRC
19:28pbostromsrid: it is also a difficult question to Google
19:28pbostrom'this' returns too many irrelevant links
19:28velvia@technomancy: thx
19:29sridafter your response, i googled for {{clojurescript "this-as"}} just to see if there are any docs talking about this-as.
19:30clizzinhey, i'm compiling a file in my test/ directory, and getting the following error: Unknown location:
19:30clizzin error: java.io.FileNotFoundException: Could not locate clojure/contrib/ns_utils__init.class or clojure/contrib/ns_utils.clj on classpath:
19:32clizzindoes anyone have any ideas? i'm using clojure 1.3.0 in my project.clj, and the only additional dependency that this test file's namespace has is midje, which i'm pretty sure works with 1.3
19:33hiredmanclizzin: have you run 'lein deps' since adding midje?
19:33clizzinhiredman: yes
19:33hiredmanis midje and ns-utils in lib or lib/dev ?
19:33clizzini just removed the require and use statements, so that all the file contains is an (ns … ) declaration at the top. i think the problem is that ns-utils is somehow not on the load path.
19:34clizzinhiredman: ns-utils is not explicitly in lib or lib/dev. i thought ns came with clojure. is that not the case?
19:34hiredmando you have the full stack trace?
19:34hiredmanns comes with clojure
19:34hiredmanns-utils is some library
19:34velvia@technomancy: how can I tell if its actually compiling the Java files?
19:34technomancyI'm not sure; I've never used javac
19:34technomancyyou can always check the classes dir if there's nothing else showing
19:35clizzinhiredman: never mind, the problem is precisely with using midje.sweet. here is the stack trace: https://gist.github.com/2871479
19:36clizzinhiredman: midge is in dev-dependencies but not in dependencies
19:36clizzinmidje*
19:46dnolenbbloom: ping
19:46bbloomdnolen: here
19:47dnolenbbloom: we should try to do something simpler for the RegExp patch, currently doing too much.
19:47bbloomdnolen: or two much for 1 patch? or period?
19:48bbloomblah fucked that sentence up. you get the idea
19:48dnolenbbloom: period. so GClosure complains if you refer to RegExp period right?
19:48bbloomexcept in a few key cases
19:48bbloomnew, obviously
19:49bbloomand instanceof
19:49bbloomand maybe one or two more
19:49dnolenbbloom: k this is the only thing we should do then ... add a new predicate called regexp?
19:50dnolen(defn regexp? [x] (js* "~{o} instanceof RegExp"))
19:50dnolenand use that in pr-seq
19:50dnolensans my typos
19:50clizzinhiredman: fwiw i just "solved" the problem by including [lein-midje "1.0.10"] in dev-dependencies instead of [midje "0.4.0"]
19:51bbloomdnolen: i'm ok with adding that predicate either way, but why not support inlining instanceof checks? we already support inlining of identical, satisfies, etc
19:54dnolenbbloom: we can though I tried that and benchmarked, make no difference in hot code.
19:54dnolenmakes
19:56dnolenbbloom: though it would be nice to lose another js* usage from core.cljs
19:56bbloomdnolen: it'd be trading a js* for a js/
19:57bbloomdnolen: besides, regexp are going to be special on every new backend
19:58dnolenbbloom: in anycase inlining instance? is a seperate thing :) regexp? for that ticket preferred.
19:59bbloomdnolen: agreed. i'll take a look at it a bit later. experimenting with the optimizations on keywords now. i think this approach i linked you to might work
19:59dnolenbbloom: link?
19:59dnolenbbloom: might have signed off before I saw it earlier.
19:59bbloomhttps://www.refheap.com/paste/2995
20:00bbloomdnolen: also worth noting (i'm sure you know this already) symbols & keywords in cljs have extra powers that they don't in clj because they are technically strings :-P
20:00dnolenbbloom: yep
20:00aperiodic}/go dor
20:00dnolenbbloom: though anyone relying on that behavior is asking for it.
20:00aperiodicoops
20:00dnolenbbloom: we may change reps at anytime.
20:01dnolenbbloom: ok, you did hear what I said about the fact that CLJS has string hash code caching right?
20:01bbloomdnolen: yeah, but i wasn't sure how that was relevant
20:02bbloomi figured that Keyword's IHash would just call hash on k
20:02dnolenbbloom: when we see a symbol, string, keyword we hash it (producing an integer) and put into cache. the next time the keyword is used, it's likely to be in the cache, so we don't rehash and use that integer value for lookup.
20:03dnolenbbloom: so it does at runtime what you're doing at compile time.
20:04bbloomdnolen: hold on, let me go look at that
20:08bbloomdnolen: ok…. so it's storing a mutable hash value on each data structure for faster successive hashing. that makes perfect sense, but i'm still not sure what that has to do with keywords :-P keywords (as strings) just call goog.string/hashCode each time
20:08dnolenbbloom: where?
20:09bbloomdnolen: grep "extend-type string"
20:09dnolenbbloom: it'll never get there, we never call -hash directly
20:10bbloomdnolen: heh.
20:10bbloomdnolen: might want to delete that than :-)
20:10bbloomthen*
20:10dnolenbbloom: no because someone might, it's there for completeness.
20:10bbloomk
20:11dnolenbbloom: one general CLJS strategy - all types implement the right behavior at the protocol level - -first, -hash etc.
20:11bbloomdnolen: makes sense
20:12dnolenbbloom: (CLJS perf strategy I mean). then fns like first, hash might make perf decisions.
20:12dnolenbbloom: because dispatching to protocol impls of native types is slow.
20:12dnolenwe don't want to pay to dispatch to nil or string.
20:13dnolenetc
20:28bbloomdnolen: did you look at http://dev.clojure.org/jira/browse/CLJS-297 ? I ask because keyword optimization interacts with objmap construction, which i change in that patch :-P
20:30dnolenbbloom: yes, refactoring patches like that are low priority.
20:31bbloomdnolen: the goal of that patch is to reduce work that the emit phase needs to do. the macros are much more reusable across backends
20:32dnolenbbloom: core.clj is filled with non-portable JS specific things.
20:32bbloomdnolen: basically, anywhere you can replace string concatenation with working with clojure forms seems like a win for modularity
20:32dnolenbbloom: you're just moving non-portable stuff into a file w/ non-portable stuff.
20:33groovemonkeyPardon, I have a list containing an integer, and I'm trying to return a keyword from it. ex: (keyword (0)) -- that returns a "long cannot be cast to IFn" error. what simple solution am I missing?
20:34seancorf`,(0) ;; that's a function invocation of zero
20:34clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>
20:34seancorf`a list containing zero is '(0)
20:34seancorf`or use a vector [0]
20:34seancorf`but you can't make a keyword out of a list...
20:34bbloomdnolen: sure, it's surrounded by non-portable stuff, but the forms are portable once the non-portable stuff gets segregated. if we're trying to push towards pluggable backends, how can i get there without moving stuff around in "refactoring" patches?
20:35nDuff...or out of a long, without making it a string first, either...
20:35groovemonkeyseancorfield: sorry, I just tested the wrong thing. It's actually this: '(0) and trying to get a keyword from it returns nil
20:35seancorfieldwhat do you mean "trying to get a keyword from it"?
20:36nDuffgroovemonkey: maybe you want (keyword (pr-str '(0)))?
20:36groovemonkeynDuff: let me try...
20:36nDuffgroovemonkey: ...but it's very unclear what your _real_ goal is for this
20:36nDuffgroovemonkey: ...why are you actually trying to make a keyword from a list containing a long?
20:37dnolenbbloom: well actually, one big advantage as macros is we get Clojure :line info.
20:37dnolenbbloom: and hopefully later column info
20:38groovemonkeynDuff: I'm working with something returned from (rest)
20:38groovemonkeyand I want to use that returned value to look up something in a map (as a part of (get-in [:x :y :z])
20:39nDuff...is there a good reason that map isn't just using plain strings as keys, then?
20:39amalloydon't use keywords *or* strings. just use the list itself as a map key
20:39bbloomdnolen: right. like i said, it's probably a maintenance and extensibility win anytime we can avoid stitching together js strings
20:40groovemonkeynDuff: Nope! Thank you for unbrainwashing me.
20:40groovemonkeyamalloy: cool, I didn't think of that either. Thank you both!
20:40bbloomdnolen: in this case, the lua backend won't need to treat vector, set, meta, or hash-map specially. they can be treated as simple invocations
20:41bbloomdnolen: which, if applicable to the backend, can be optimized with macros
20:42dnolenbbloom: no effect on compile time?
20:43bbloomdnolen: benchmark you mean? i didn't run it.
20:47bbloomdnolen: script/benchmark for runtime perf, where is compile time perf measured?
20:47dnolenbbloom: I generally just do, "time ./script/test"
20:48bbloommy machine probably isn't the most reliable benchmark target…. lots of stuff running & it's a puney macbook air w/ the older cpu...
20:48bbloombut running it anyway
20:52dnolenbbloom: I'm not seeing any real diff far as compile time. I'll ponder the patch some more.
20:53bbloomdnolen: i ran it twice on master and twice with that patch. bounced back and forth around a minute plus or minus 5 seconds
20:54bbloomdnolen: ok, ponder the whole scope of similar refactorings. i cansee a whole bunch of opportunities to beef up code reuse between backends, while minimizing code per emit backend
20:55dnolenbbloom: I'm all for refactoring for backends. But the macros file is something that will need to be different for different backends.
20:55bbloomdnolen: also, this particular change probably has an opportunity to speed up compilation quite a bit if we move a bit of this logic into the reader. this way the reader would never need to produce a map or vector or whatever
20:56dnolenbbloom: the reader is the Clojure JVM reader.
20:56bbloomdnolen: i realize that, but it doesn't have to stay that way :-)
20:57dnolenbbloom: true, but expect patches to CLJ to move much slower than CLJS :)
20:57bbloomdnolen: right now when you read {:x 1} you get a map, but if you instead got (list 'hash-map :x 1) then you could cut out a whole bunch of logic from analyze phase
20:58bbloomdnolen: but beyond that, you wouldn't need to build the whole red black tree, etc. would probably speed up compilation quite a bit
20:58hiredmanI imagine most read maps end up being array maps
20:58bbloomdnolen: actually, would be (list 'hash-map (keyword "x") 1)
20:58bbloomer 'keyword
20:58bbloomyou get the idea
20:59bbloomor 'core/keyword or whatever
20:59hiredmanbbloom: how do macros work with that?
20:59dOxxxHi... I'm having some trouble with flatten and pmap...
20:59johnmnmnso weird... lein uberjar is not returning errors, but still no jars show up in my project dir
21:00dOxxxwhen I do something like: (flatten (pmap my-func some-list)) it seems to undo the parallelization of pmap and process it sequentially
21:00bbloomhiredman: i'm talking about deferring construction of the map during read
21:00johnmnmn"Compilation succeeded."
21:01hiredmanbbloom: but the output of the reader is what is passed to macros
21:03bbloomhiredman: call eval on it? :-)
21:03aperiodicjohnmnmn: which version of lein?
21:03dnolenbbloom: heh, yeah that's not going to go anywhere.
21:04bbloomdnolen: call very-simplistic-eval-which-only-understands-basic-calls-to-native-data-structures on it? :-)
21:05johnmnmnaperiodic: lein1
21:06aperiodicjohnmnmn: hmm, that is odd. you didn't set :jar-name or :uberjar-name in your project.clj, did you?
21:06johnmnmnaperiodic: I did not
21:08aperiodicjohnmnmn: is lein jar showing the same symptoms?
21:08johnmnmnaperiodic: https://www.refheap.com/paste/2998
21:09johnmnmnyes, it is.
21:09aperiodicoh, well, the uberjar is failing because you have snapshot dependencies in a release version
21:10dOxxxany insight on why flatten would negate the parallel-ness of pmap?
21:11johnmnmndOxxx: I don't think it would
21:12dOxxxjohnmnmn: it is. :P
21:12johnmnmnI've recently used reducers -- r/flatten (r/map -- to good effect
21:13dOxxxthat's in the latest clojure alpha, right? how unstable is the alpha in general?
21:14dOxxxbtw, this the code in question: https://www.refheap.com/paste/2999
21:15dOxxxthat code for a particular dataset runs in about 16 seconds
21:15dOxxxif I use this instead: https://www.refheap.com/paste/3000 then it runs in about 5 seconds
21:16dOxxxif I take a thread dump while the first version is running, all the calculation is being done in one thread and there's no sign of pmap in the stacktrace
21:16dOxxxwherease the second version shows multiple threads doing the calculation and another thread with pmap in the stacktrace waiting on the other threads to finish
21:17johnmnmndOxxx: how heavy-weight is parse-line?
21:17dOxxxit's a few regex and constructing some records
21:17johnmnmnso it kinda depends on how heavy weight the payload is.
21:18dOxxxit's fairly lightweight as I understand it which is why I wanted to try batching it up to reduce context switching overheqad
21:19dOxxxup to 4 regex and one record
21:19dOxxxregex are operating on a single line of text
21:20johnmnmngenerally, I think pmap and friends do the appropriate level of chunking for you
21:21amalloydOxxx: parse-batch takes zero time
21:21dOxxxoh? interesting...
21:21amalloyso parallelizing it is a waste of resources
21:21amalloybecause it instantly returns a lazy sequence of lines
21:21johnmnmnnot sure if it dynamically detects the weight of a given chunk, and expands as necessary, but it does chunk in the background
21:22dOxxxso (pmap parse-line lines) is just doing the right thing automatically?
21:22dOxxxcool
21:23dOxxxI also discovered that concat does not work well with large lists :P
21:24dOxxxI was trying to write a replacement for flatten as (reduce concat list-of-lists) but it died with a stack overflow error
21:24mthvedtreducing lazy sees can cause stack overflows
21:25mthvedtfor reasons i don't remember the details
21:25dOxxxany workaround?
21:25mthvedteager seqs
21:25dOxxxis that function?
21:25mthvedtmaybe wrap a doall
21:25dOxxxah ok
21:26TimMcclojurebot: prime overflow?
21:26clojurebotIt's greek to me.
21:27TimMcclojurebot: sieve
21:27clojurebotsee the genuine sieve of eratosthenes
21:27TimMcbah
21:27amalloy$google stackoverflow dbyrne sieve clojure
21:27lazybot[recursion - Recursive function causing a stack overflow - Stack ...] http://stackoverflow.com/questions/2946764/recursive-function-causing-a-stack-overflow
21:34dOxxxgot the batching working by throwing in a bunch of doalls to de-lazy the various sequences and it doesn't perform any better than the non-batch form.
21:34dOxxxso yay pmap for being smart
21:36dOxxxthanks for the help :)
21:42johnmnmnjust used lein2 and still no juju :/
21:43dOxxxjohnmnmn: post your project.clj?
21:43dOxxxwho knows, maybe the newb will spot something :)
21:47bbloomdnolen: updated http://dev.clojure.org/jira/browse/CLJS-300
21:49johnmnmndOxxx: https://www.refheap.com/paste/3001
21:50johnmnmnI didn't notice 'lein uberjar' always saying this before: Release versions may not depend upon snapshots.
21:50dOxxxjohnmnmn: have you tried: :main "SMCQ.core" ?
21:51dOxxxjohnmnmn: [21:04:45] <aperiodic> oh, well, the uberjar is failing because you have snapshot dependencies in a release version
21:52johnmnmnhuh?
21:52muhooordinary jars (lein jar) seem to have no problem with snapshot dependencies. uberjars apparently do.
21:54johnmnmnhmm
21:55johnmnmnlein jar has been doing the same thing... trying again now
21:55johnmnmnyea, no bueno
21:56johnmnmntrying with a different clojure version
21:57johnmnmndeleting my .m2/repository too
22:03muhoojohnmnmn: if you're using lein2, try "lein2 deps :tree"
22:04muhoosee if there are any SNAPSHOTs in there. if so, whack them.
22:04johnmnmnmmm, k
22:07johnmnmn org.clojure:clojure:jar:1.5.0-alpha2
22:08johnmnmnis this correct: [org.clojure/clojure "1.5.0-alpha2"] ?
22:08johnmnmnmaven can't find it.
22:08dOxxxalpha1 is latest
22:08johnmnmnalpha2 is out there
22:10johnmnmnalpha.2?
22:10dOxxxI don't see alpha2 in the list of tags on github
22:11johnmnmnhmm
22:11dOxxxnor do I see it here: http://mvnrepository.com/artifact/org.clojure/clojure
22:12johnmnmnI guess your right
22:12johnmnmnwonder why I thought that
22:12dOxxxyou're living in the future
22:12muhooTimMc: yes, and i found a cleaner way to do it, (some #(boolean (re-find % uri)) [#"^/css" #"^/js" #"^/img"])
22:12johnmnmnI blew my cover
22:13dOxxxare you going to have to kill me now? :(
22:13johnmnmnNo, I just have to kill this identity now
22:14dOxxxstyle question: should I use (->SomeRecord stuff) or (SomeRecord. stuff) in code which is in the same namespace as the SomeRecord definition?
22:16johnmnmngetting a lot of this: [WARNING] Overriding profile: 'null' (source: pom) with new instance from source : pom
22:16johnmnmnand: [INFO] Unable to find resource 'org.clojure:clojure:pom:1.+' in repository cloja
22:17johnmnmnoh wait: Release versions may not depend upon snapshots.
22:18johnmnmnis that saying that it is interpreting my project as a "release version" because I don't have the word "SNAPSHOT" in it?
22:20johnmnmnomfg, that was it
22:21dOxxxjohnmnmn: yay? :)
22:21johnmnmnyay is right
22:21johnmnmnI blame myself for not understanding the error language that was in front of me the whole time.
22:25muhoothat's kind of weird. i've build jars of release versions which depend on snapshots before. i don't get any complaints.
22:25muhoomaybe, again, uberjars are different.
22:31johnmnmnso have I
22:35TimMcmuhoo: The call to boolean is unecessary.
22:36muhooTimMc: i wondered about that. thanks.
22:48johnmnmnI love writing little clojure tools to get stuff done at work... Its just so easy to use the many libraries out there to get things done.
22:50johnmnmnpeople at work are always so surpised when I drop a 50 meg jar file on their desktop that can parse PDFs, excels, out put graphs, more excels, scrape intranet sites... all in a couple days.
22:50johnmnmnand their surprised
22:53mheldwhat do y'all use for routing? clout? moustache?
22:54brehautyou probably mean compojure rather than clout
22:54brehautclout is used internally by compojure
22:54mheldoh, didn't know that
22:55brehautand compojure is the most common choice these days, it has the largest community and is probably easiest to get going with
22:56mheldyeah, I'm getting into webdev with clojure and there doesn't seem to be central defacto guide anywhere
22:56mheldI mean, I'm piecing things together
22:56brehautstart here http://brehaut.net/blog/2011/ring_introduction
22:58brehautmheld: it might be a bit lower level than you were expecting, but ring is the foundation of web stuff in clojure. understanding it will make everything that follows easier
23:01mheldbrehaut: cool, thanks
23:02mheldbrehaut: great article :-)
23:02brehautyour welcome
23:07readmemheld: =o
23:08mheldreadme: god damn it, are you in *all* the rooms I'm in?
23:08readmejust 2 others, i think
23:08mheldhaha
23:08mheldand you're in boston, right?
23:08mheld(ish)
23:08readmeyep
23:08mheldare you an alter ego of mine?
23:08nsxtreadme: were you at the clojure meetup a few weeks ago?
23:09readmei wasn't.
23:35meahowdy
23:35meais a Keyword just like a special variable?
23:36meaI don't really understand why it is used
23:39mthvedtkeywords are interned literal
23:39mthvedtlike strings, except a little more convenient for some things
23:42tomojpotemkin is impossible in cljs, right?
23:50Rayneshttps://www.refheap.com/paste/3000 3000 pastes.
23:50RaynesWoot.