#clojure logs

2010-05-07

00:09rdsrhelp
00:09rdsrexit
00:09rdsrquit
00:13defnrdsr: /quit
00:18technomancywho was asking about pretty representations of fn objects?
00:18technomancyhttp://github.com/technomancy/serializable-fn
00:18technomancy^_^ check it out
00:20defntechnomancy|away: awesome!
00:23joshua-choiIs there an RSS feed for Clojars?
00:36arohnertechnomancy|away: that's really clever
00:49tomojhmm, I get an "Unmatched delimeter: )" trying to slime-connect to the lein swank I get in that project
00:50remleduffI think that's clojure-test mode or whatever the test mode is called
00:51tomojoh fuck
00:51tomojnow I can't connect to a mvn clojure:swank in my other project
00:51hiredmantomoj: yeah, you have to grab the latest clojure-test-mode from github
00:52tomojhiredman: technomancy's?
00:52hiredmanyeah
00:52tomojhasn't changed since april it looks like
00:52hiredmanyou can just replace the clojure-test-mode you have in ~/.emcas.d/epla/ with it
00:52tomojwhy did this problem just now happen to me, I wonder?
00:53hiredmanI had this error too, and replacing test-mode with test-mode from git fixed it
00:53hiredmanand I got this advice from technomancy
00:53hiredman,Q
00:53clojurebot<-nil-<
00:54tomojyep, fixed it, thanks
00:54tomojstill wonder why, though..
00:57remleduffGoing by the github commit, he was using ^ to mean (meta) in one place, which broke with the 1.2 changes
01:00tomojis it totally gone now, no longer just deprecated?
01:01remleduffYeah, ^ is for type hints now
01:01tomojoh, like ^String ?
01:01tomojcool
01:01remleduffYep
01:01tomojI tried that earlier and it didn't work
01:01tomojso I must have just gotten a 1.2.0 update which caused the error
01:04joshua-choiremleduff: Does #^ still work in Clojure 1.2 for now? Is it deprecated?
01:05remleduff#^ is still ok
01:05remleduffOnly ^foo -> (meta foo) is gone
01:05remleduffI guess #^ must be deprecated if only because it's ugly ;)
01:07tomojI'm glad type hints will be prettier
01:07tomojI could never really remember how to do them
01:10remleduffI guess #^ will probably stick around for quite a while if library try to support both 1.1 and 1.2
01:23DuneMandarnit
01:24DuneMansomething is holding onto the head again
01:24DuneMan*watches memory rise*
01:24DuneManthis is becoming a real problem....
01:24hiredmanpastebin your code
01:24DuneManSo, what is the correct way to write code using infinite seqs to stay away from such things?
01:24DuneManhired: It's spread over 7 files
01:25DuneManand does a bunch of stuff
01:25hiredmanDuneMan: if you can't reduce it to a simple test case there isn't much anyone can do for you
01:25hiredmanwe will just get annoyed listening to you complain about something you aren't able to demonstrate
01:25DuneManThere are, however, best practices when dealing with such things.
01:25hiredmanthe best practice is don't hang on to the head
01:26hiredmanmost likely you are inadvertently doing it
01:26DuneManThey can tell you what sorts of operations do this often... e.g. (apply (partial ...) infinite-sequence) ; badness
01:27DuneManI know I am. And I'll find this specific case, again. Just wondering if there's a general form that makes it happen less often. Like doing (lazy-seq (...)) and recursing?
01:27hiredmanit depends on the functions you partial
01:27hiredman,(apply first (cycle [[1]]))
01:28clojurebotExecution Timed Out
01:28remleduffWhen did fine grained locals clearing get added, is that 1.2 or was it 1.1?
01:28DuneManactually, it doesn't depend on the function you partial. Because partial take [& more]
01:28hiredmanDuneMan: it does dpeend on those functions
01:28DuneManthe functions returned by partial*
01:28joshua-choiremleduff: I believe it was 1.1.
01:28hiredmanjoshua-choi: no
01:28joshua-choiOh dear
01:28joshua-choiIs it being added in 1.2?
01:28hiredmanI belive it wasn't
01:28DuneManI was seeing massive problems in 1.1, and going to 1.2 made things a lot better.
01:28hiredmanyes
01:29DuneMan1.2 at least made it so every case I've seen of this happening has been my fault.
01:29hiredmanthe change was invasive to the compiler and made close to the release of 1.1 so it was decided to wait until 1.2
01:29hiredman,(apply (fn [& _] 1) (iterate inc 0))
01:30clojurebot1
01:31hiredmanDuneMan: (partial head-holding-function 1) <-- resulting function still holds on to the head
01:32DuneMan*looks to see if he is still using the code that leaked memory with partial but not withour*
01:32tomojare there still cases where you're holding onto the head but even if you meditated on the problem code for a while you wouldn't notice unless you had some deeper knowledge of the compiler?
01:33hiredmandunno
01:33hiredmanit used to be possible to do it without knowing by using destructuring in a loop binding
01:35DuneManI'm no longer using the code that was head-holding with (partial...) and apparnetly I didn't do a commit with that version
01:36DuneMantoo bad I'd like to see what my function was doing that was holding the head.
01:36DuneManI fixed it by replacing (partial...) with my own function that returned a function of 1 arg instead of variable args
01:36parasebaHi all. What's the idiomatic way to insert an element in a vector?
01:36DuneManand using it to wrap the same function.
01:37parasebaI mean insert an element in the middle of a vector
01:38DuneManIt'd be useful to find a good tool for figuring out what was holding the head. Sorta hard with all the java tools because they assume a meaningful class name for things holding references.
01:38DuneManany suggestions there?
01:38joshua-choiparaseba: Actually, it's idiomatic to not use vectors if you need to insert in the middle of it
01:38joshua-choiI think
01:39hiredmaninsert can mean different things
01:39hiredmando you mean grow a vector by inserting into the middle, that is messy
01:39parasebahiredman: yes, exactly that
01:39hiredmandon't do that
01:40hiredmanif you are doing that you are doing it wrong
01:40parasebaI know it sounds weird, the fact is that I'm writing a macro that modifies the result of a function which already returns a vector
01:40hiredmanit's not weird, it is bad
01:40parasebaI need to return a new vector with an added element
01:40hiredmanvectors "grow" in one place
01:40hiredmanthe end
01:42parasebahiredman: vectors are short, and part of a templating system, changing vectors to other structure is not an option. This is some sort of wrapper which gets the result and add an extra element in the middle
01:42parasebabut I guest the answer is "there is no idiomatic way ... no one ever does that stupid thing"
01:43parasebait makes sense ...
01:43hiredmanparaseba: how is not an option?
01:43joshua-choiparaseba: If you really need to (and since it's a macro, performance doesn't matter that much anyway), I'd use subvec twice with into.
01:43hiredmanchanging vectors into other structures is done usually without thinking about it
01:43hiredman,(map inc [1 2 3])
01:43clojurebot(2 3 4)
01:44hiredman,(vec (concat [1] [2] [3]))
01:44clojurebot[1 2 3]
01:44joshua-choihiredman: Incidentally, is there a function for lazily inserting something into the middle of a seq?
01:44hiredmannope
01:45parasebahiredman: yes, but that's exactly my question ... there are several ways in which I could transform the vector to a seq, add the element and transform the result back to vector
01:45arohnerjoshua-choi: you'd need to evaluate up the start of the insertion point
01:45joshua-choiarohner: If there was a way to pass on the current index, perhaps not...
01:46hiredmanarohner: no you wouldn't
01:46hiredman,(let [x (iterate inc 0)] (take 10 (concat (take 3) [-1] (drop 3))))
01:46clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$take
01:46hiredman,(let [x (iterate inc 0)] (take 10 (concat (take 3 x) [-1] (drop 3 x))))
01:46clojurebot(0 1 2 -1 3 4 5 6 7 8)
01:47joshua-choiAha
01:47hiredmanthere may be one in seq-utils, or whatever it is called now
01:48joshua-choi.seq, I believe
01:55LauJensenMorning all
02:00DuneManSo, my infinit seq is actually just: (repeatedly #(.take queue)), and I guess since the caller is what is doing the (repeatedly...), it happens that its holding the head somehow... even though it's not doing it in a let-binding or anything. This whole sequence is consumed in a single (doseq [e es] ....)
02:01DuneManIf I replace this with passing the queue (a LinkedBlockingQueue) into my handler function, and doing (loop [] (println (.take queue)) (recur)), it indeed does not kill memory.
02:03hiredmanDuneMan: what is es?
02:04DuneManI think I can pastebin the functions up to that and it will make sense. 1 sec.
02:13DuneMan('es' is passed into the function as an argument, (handler-function (repeatedly #(.take queue)))
02:13DuneManhttp://pastebin.com/L9ubTrBq <--- no memory leak with doing the .take within the innermost function
02:18DuneMan.... and now I reverted my code and the memory usage is stable.
02:19DuneManhttp://pastebin.com/1WWyccYf
02:19DuneMannot my day, apparently.
02:22tomojdouble spaced?
02:22tomojwtf?
02:22DuneManMaybe the memory growth was just the JVM not being able to keep up with GCing stuff... I had a rogue process on the box eating 7gb of ram and a lot of CPU... and this thing is reading in a few megs a second.
02:22DuneManYeah, I have no idea why pasebin did that?
02:23tomojthat is very disorienting to me
02:23DuneManit looks aight in the text box when I pasted it
02:23tomojI wonder if they do that all the time?
02:24DuneManI also wonder if implementing this with agents would perform.
02:25hiredmanyou should try paste.lisp.org or gist
02:25DuneManoh, queue-seq is a macro that expands to (repeatedly #(.take queue))
02:25DuneManah, good to know.
02:26DuneManand now this is humming along swimmingly and the jvm+gc is getting warmed up and memory is dropping
02:26DuneMan.... maybe it was just not keeping up.... goddamn.
02:30DuneManhave any of you used agents to implement stream-type processing?
02:31DuneManWhere you are reading a stream of messages which are ordered and need to do processing on them in a potentially order-dependent manner?
02:32DuneManthe model didn't seem to fit quite right, but I'm not sure I totally understand yet :-)
03:22sidswhat is the meaning of the '-SNAPSHOT' in version numbers of clojure and other clojure projects?
03:23sparievsids: thats maven thing
03:24sparievSNAPSHOT is a special version in maven that indicates the latest code; typically TRUNK or HEAD in your source control.
03:24sparievWith this version, maven will automatically grab the latest SNAPSHOT every time you build
03:24sparievleininigen follows this convention too
03:24sidsspariev: thanks. So if I'm going to release a library version 1.0, say, I should push 1.0-SNAPSHOT to clojars?
03:25sparievsids: if youre planning to update this release frequently, maybe you should
03:25sidsand bug fixes for the 1.0 release should also be pushed with the same 1.0-SNAPSHOT version? did I understand this right?
03:26sparievI think yes
03:27sidsthanks
03:27DuneManIt seems to me that you should branch for you release versions
03:27DuneManand also push a snapshot version of latest-version+bump
03:27sparievbut once you have your codebase stabilized, you should drop SNAPSHOT
03:27DuneManer, release-version+bump
03:29sidshm, this is a bit confusing. Can I update a release-version-SNAPSHOT with bug fixes or do I push a new release-version-bump-SNAPSHOT?
03:33sparievI would go with the release-version-SNAPSHOT if you are going to have frequent changes and bugfixes, so your users won't have to change their dependencies every time bug fix arrives
03:33remleduffIn general for code you're making available to other people, it's better to just do released versions like 1.1, 1.2, it's not like you're going to run out of numbers
03:33remleduffSNAPSHOT is really meant for local builds, it's being abused by our community somewhat
03:34DuneManAnd then you should push bug fixes in bugfix bumps
03:35DuneManI think the leiningen git page links to a recommended version style
03:35sidsthanks everyone
03:35DuneManindeed it does
03:35DuneManhttp://semver.org/
03:35sexpbot"Semantic Versioning"
03:36sidsyeah, I read that, but it does not mention anything about -SNAPSHOT
03:37DuneMan-SNAPSHOT just means that you took the current head of your repo, in your development version number, and packaged it.
03:37DuneManit may even not work.
03:38DuneManthough probably should :-)
03:38remleduffIt actually resolves to a timestamp-ish looking thing, like clj-json-0.2.0-20100215.165114-2
03:39remleduffThat's actually clj-json-0.2.0-SNAPSHOT from when I downloaded it
03:39sidsI'm just publishing a lein plugin to clojars; lein uses the -SNAPSHOT, so I'm going to use it too, for now :)
03:40sidsremleduff: that is very informative. How did you find that out?
03:40DuneManThat's what will be in your /lib directory.
03:40DuneManwhen you do lein deps
03:40sidsoh, never looked there, makes much more sense now. Thanks!
03:42remleduffIn maven world, once you release a non-snapshot version, you're never supposed to change that version again because people are supposed to be able to depend on it. SNAPSHOTS can change without warning
03:42remleduffIn clojure world, people tend not to release often enough so lots of people end up running SNAPSHOT versions
03:45sidsmakes a lot of sense, not that I understand that SNAPSHOTs are really pointers, not fixed releases
03:45sidss/not/now/
03:45sexpbotmakes a lot of sense, now that I understand that SNAPSHOTs are really pointers, now fixed releases
03:46DuneManI do like that feature of irc bots.
04:18zmilas/do/don't/
04:18sexpbotI don't like that feature of irc bots.
04:18zmilahohoho
04:53LauJensentest
04:53LauJensens/test/$(println "test")
04:53LauJensens/test/$(println "test")/
04:53LauJensenJust wondering if he read what he wrote, and if he did, if he had access to more functions than I do :)
05:46jwr7So I'm trying to move my deftests out of my code and into the test/ directory (using leiningen), and I just discovered that if I do this, my test namespaces can't access private symbols defined using defn-, and so my tests won't work.
05:46jwr7How do people get around this?
05:46jwr7In fact, I'm not entirely sure I want to move my tests out into a separate tree — what I need is a way to run them all using lein.
05:48AWizzArdjwr7: can your tests go (in-ns ns-with-private-fns)?
05:48AWizzArd(in-ns (quote ns-with-private-fns)) I mean
05:49jwr7AWizzArd: I guess so — so instead of declaring a new namespace for my tests, I could just… but then I also have to load the ns-with-private-fns before, I guess.
05:51sidsjwr7: I create a test dir and then symlink my tests into that
05:55jwr7java.lang.Exception: Unable to resolve symbol: use in this context. I guess my in-ns placed me in an incomplete namespace somehow?
06:04jwr7Ok, got past that (typo), but now lein doesn't seem to find my tests. lein test says "Total: {}".
06:10jwr7AWizzArd: ok, that won't work. lein uses clojure.contrib.find-namespaces to find namespaces in test directories, so you actually need to define a NEW test namespace, not use an existing one.
06:10jwr7Which brings me back to my original question — phrased differently, is there a way to :use a namespace WITH private symbols?
06:21LauJensenjwr7: Does it make sense to test privates only? I expect them to be wrapped by something publicly exposed, which makes more sense to test?
06:22jwr7LauJensen: good question, I pondered it as well. Still, those *are* supposed to be *unit tests*, right? And in my case, I very often have private functions, whose behavior is best described by tests.
06:22jwr7If I go a level up, my tests will confuse various functionalities and become large, unwieldy and hard to maintain.
06:22LauJensenjwr7: if I make (defn add3numbers [x y z] (+ x y z)) - I test that with pos, neg, nil etc, but I dont separate unit-test "+"
06:23LauJensens/separate/separately/
06:23sexpbotjwr7: if I make (defn add3numbers [x y z] (+ x y z)) - I test that with pos, neg, nil etc, but I dont separately unit-test "+"
06:24jwr7LauJensen: of course. But in case of more complex packages you often have internal functions with non-trivial functionality.
06:25LauJensenthat cannot be validated by seeing succesful tests on the top-level fns ?
06:25LauJensenie. where its possible to have a private regression which doesnt affect the public fn ? is that even a regression? :)
06:25jwr7LauJensen: as an example, think of a text search package. You'd have externally accessible 'search' and 'compute-index' functions and internal scoring functions. You don't expose the scoring functions to the external world, but you want to test them separately.
06:25jwr7LauJensen: and I can definitely achieve lots of regressions in the private functions :-)
06:26LauJensenjwr7: You could be right, Im just saying I wouldnt start hammering out those tests up front :)
06:26LauJensenjwr7: I know you can - Im just saying, that'll show up in the higher levels as well
06:26jwr7LauJensen: oh, sure. My approach to tests is very pragmatic, I try to do as few as possible and still get the benefits.
06:26LauJensenie, if you break score in a way, which still produces all the correct results, for all the tests on search, then who cares?
06:27jwr7LauJensen: they *will* show up in the higher levels. But then you don't have unit tests anymore. You have higher-level tests, and if they fail, you have to investigate where is the actual problem. Plus, these tests tend to get difficult to maintain (from my experience).
06:28jwr7LauJensen: trick is, you don't want to hardcode the "correct results" on a higher level. You want them to be as close to the actual code as possible. That's the idea of unit testing, as opposed to component testing.
06:28jwr7I'm not saying the latter isn't useful, of course.
06:28LauJensenYea I see what you're saying
06:28LauJensenAnd I guesss the higher levels fns, often fit more into integration tests, than unit tests
06:29jwr7LauJensen: right.
06:29jwr7LauJensen: as another example, I used to develop weblocks, a CL web framework. Higher-level tests always ended up being "run this thing and compare the resulting HTML to this string". Completely unmaintainable in the long run.
06:30jwr7You would change a tiny function and then have to modify 100 test strings.
06:30LauJensenpainful
06:31Chousukehmm.
06:31jwr7I tend to think of unit tests as an extended docstring, of sorts — they document the corner cases. Hmm, perhaps separating them from the functions isn't a good idea after all?
06:31ChousukeI'm more partial to the idea of writing only regression tests :P
06:32Chousukeat least with languages like clojure
06:32Chousukewhere it's easy to test every function after you've written them.
06:32DuneManI am hopeful I've figured out how to write correct code with lazy seq
06:32DuneManmemory isn't growing... woo
06:33jwr7Chousuke: I disagree, but perhaps I tend to introduce more bugs :-)
06:33LauJensenChousuke: Im with you on that
06:33Chousukesomething like QuickCheck is useful too though.
06:33jwr7Chousuke: regression tests don't capture the corner cases, as those won't make it through the higher-level functions. So they don't future-proof your code, as unit tests do.
06:33Chousukewhere you have a dumb but certainly working reference implementation and a test data generator
06:34Chousukejwr7: unit tests don't help either if you don't write the correct ones :/
06:34jwr7Also, mind you, I'm not a test fanatic — I don't write tests for everything, only for non-trivial functions. My tests are essentially a saved REPL session.
06:34jwr7Chousuke: true, but writing them helped me discover problems with corner cases. I guess it's a way of disciplining myself to check.
06:36LauJensenjwr7: corner cases? You know Clojure is Functional right? Which corner cases do you mean
06:36jwr7LauJensen: passing an empty sequence, which causes a division by zero later on
06:37AWizzArdTesting pure functional code is not very important (+, fibonacci, str, assoc, etc.). But the state changing parts should indeed be tested. Tests can also help to develop a useful API.
06:38LauJensenjwr7: (defn divme [x y] {:pre (not (zero? y))} (/ x y))
06:38LauJensenthere's a time and a place for everything
06:39jwr7LauJensen: Oh. In my case (a scoring algorithm) I had to special-case this and return a score of 0.0. So it wasn't really a precondition.
06:39jwr7I don't test functions with are a simple composition of clojure or library stuff.
06:40jwr7So if all I do is reduce, map, into, etc — I don't need tests for that.
06:41ChousukeI suppose writing tests is an improvement; at least you're tempted to think "tests pass, ship it" instead of "it compiles, ship it"
06:41DuneManIt's sorta confusing writing functions that work right with lazy-seq... but I think I'm getting it. A bit convoluted to have a function that returns a lazy-seq in which is defined a function which is recursive with itself, and as a base case returns its value and then is recursive with the outer function.
06:41DuneManbut it works, and it doesn't consume tons of memory. and is ... concise.
06:41jwr7Chousuke: yeah, that too. But for me there are two advantages: 1) they form an extended specification and 2) they help me discover corner cases I haven't thought of. Regression testing is actually an afterthought in my case.
06:45DuneManjwr77: While I agree testing can work well that way, I think it can still happen in that workflow with keeping tests in a seperate file.
06:46DuneManI think its particularly important to have them separated when you go in and start hacking on code to change functionality.
06:46DuneManIt becomes to easy to break test code.
06:46DuneMantoo*
06:47DuneManerrant find/replaces, and whatnot... the same types of bugs that break other code... the code you want the tests to be sanity-checking (in the regression case)
06:56DuneMang'night all, thanks for the help all day.
06:59Borkdudedefn: here?
07:22BorkdudeI was searching for a nice example with -?>
07:22BorkdudeBut this doesn't work: http://getclojure.org:8080/examples/-?%3E
07:22Borkdudehttp://getclojure.org:8080/examples/-?&gt;
07:26BorkdudeI was thinking smth like this:
07:26Borkdude(-?> {:a {:a2 "A"} :b "B"} :a :a2)
07:26Borkdudevs (-?> {:a {:a2 "A"} :b "B"} :b :b2)
07:26Borkdudebut that's kind of what get-in is for
07:31Borkdudeit's a terrible macro name to search for on the internet
07:57sidsBorkdude: (-?> #"hello" (re-matches "hello") .toUpperCase)
07:57sidsBorkdude: vs (-?> #"hello" (re-matches "goodbye") .toUpperCase)
08:09Borkdudesids tnx
08:11Borkdudesids, I will mention your example on @cleotd ok?
08:25jowagIf I close over a java object, and I do not keep other references to that object other than from the closure itself, will the object be garbage collected (bad) or it will be garbage collected only after I let go the reference to the closure (good)?
08:28chouserjowag: the latter
08:29chouserjowag: no worries, you're all set.
08:32jowagthank you
09:11fogus,Q
09:11clojurebot<-nil-<
09:12Borkdude?
09:13cgrandBorkdude: http://clojure-log.n01se.net/date/2010-05-06.html#16:02
09:13sexpbot"#clojure log - May 06 2010"
09:14cgrand$"http://clojure.org/&quot;
09:14sexpbotCommand not found. No entiendo lo que estás diciendo.
09:14cgrand$(identity "http://clojure.org/&quot;)
09:14sexpbotresult: http://clojure.org/
09:16Borkdudechouser: I like the fish skeleton
09:21fogusI couldn't resist adding the fish queue to the book last night.
09:22Borkdudeclojure powered ascii art, the beginning of a new genre
09:23fogusLauJensen already blazed that trail. http://www.bestinclass.dk/index.php/2010/02/my-tribute-to-steve-ballmer/
09:23sexpbot"My tribute to Steve Ballmer | BEST IN CLASS"
09:29Borkdudehmm, that is ascii photographism, not as exciting as handcrafted works imho ;)
09:31chouserI love the stunning lack of type hints required in programs that use protocols extensively
09:33LauJensenConversely I love the astounding lack of protocols, in programs which use type hints extensively
09:33chouser:-(
09:35LauJensensorry, just kidding
09:35LauJensenBut I've yet to see a problem which really leverages protocols
09:39cemerickcgrand: that's a horrible tale. :-(
09:40cgrandcemerick: what? my tweet? yeah :-(
09:40cemerickyeah
09:40chousernoooo
09:40cemerickI don't think there's a pithy slogan in "bring back the :use errors"
09:40defnBorkdude: oy, i don't think that's on the whitelist of functions for the sandbox
09:41chousercgrand: he still gets a warning, right? He's just going to ignore it?
09:41cemerickchouser: programmers have been trained to ignore warnings since the 7th day.
09:41cgrandapparently yes
09:42jfieldsis there a better way to do this: (+ (or x 0) quantity) - where x could be nil, but quantity never would be.
09:43eleanha I discovered the stack overflow in my code.. funny thing, if you got ref on vector containing the ref itself it may not be that easy to print it
09:44cemerickcgrand: you should post on that on the dev list or something -- a good horror story might be a good motivator. :-)
09:44chouserelean: should be able to set your *print-level* to avoid problems with that
09:44chousercemerick: the solution would be :as-of ?
09:45AWizzArdjfields: what you have is a good solution
09:45eleanchouser: wow nice thanks
09:46jfieldscheers.
09:47cemerickchouser: I've been mostly absent from the :as-of and last-var-wins discussions, but the latter definitely rubs me wrong. :as-of is version sniffing IIUC, which is always bad IMO (and wouldn't help w.r.t. third party libs?). As I understand the problem, it seems that being smarter about definitions in general is the best route, perhaps with feature-conditional evaluation (as opposed to version sniffing).
09:48cemerickI proposed the former yesterday, but I'm guessing it's too complex to tackle for 1.2.
09:48cemerickchouser: http://groups.google.com/group/clojure/msg/86384d7e6555c024
09:49chousercemerick: yeah, I raed that message a couple times. I don't think I understand yet exactly what you're proposing.
09:51cemerickchouser: it's a significant complication to the reader if namespaces aren't held in refs, or something similar. i.e. "load" the namespace without def'ing anything, and see if any defs will clash with referred vars; if so, bail, otherwise, proceed. This makes it trivial to predefine all the vars in the ns, eliminating the need for declare. This was a hot issue a long while back.
09:52cemerickIf namespaces were in refs, then it gets a *lot* easier -- just create the bare ns in a ref, and attempt to load it within an alter.
09:53cemerickIf there's no error, then you're good -- otherwise, all the namespaces are left in a pristine state, so you can't get into trouble at the REPL either.
09:53chouserbut isn't the whole reason for address this now the problems caused by simply bailing when two :use'd libs clash?
09:54cemerickWell, that problem's been around forever. I think the latest spate of activity is to give some relief to people whose var names are being shadowed by core in 1.2 (and later releases).
09:55cgrandchouser: to me if two :use clashes the user deserved it, my only concern is about clashes with core
09:55chouserright. that's the problem we're trying to solve, and I'm not seeing how running through the lib ahead of time helps with that.
09:55cemerickIf you're doing some work with var name checking before actually def'ing anything, you can ensure that you don't refer in any conflicting names -- the local one can always win, without any last-first-in-the-middle-wins behaviour.
09:56cemerickchouser: if two :use clauses clashing is the problem being solved, that's the wrong problem to solve IMO.
09:56cgrandcemerick: to me :as-of is not some version sniffing, it's just a shortcut to says (:refer-clojure :only [vars known at the time of writing]) because this only is tedious to maintain by hand
09:57cemerickI thought clashes with new vars in upstream libs was the real target.
09:57cemerickcgrand: it's roughly the same as doing (if (= "1.2" *clojure-version*) (refer ......)) *shrug*
09:58cemerickBut, I don't have a lot of ground to criticize :as-of. It seems like a very limited mechanism though -- e.g. not useful by third-party libs.
10:00cemerickThe reordering of :use declarations though -- that's just evil. Underhanded. Sneaky. Must be killed with fire.
10:00cemerick;-)
10:01cgrandon 3rd part lib: unless they start adding :added metadata -- but anyway you shouldn't use without :only a ns you don't own
10:02cemerickcgrand: I mostly agree with you. c.c.core and c.c.def are exceptions IMO. Others may have different ones.
10:03chousercemerick: local winning seems like a plausible goal, but if core and some other lib clash, which is "local"?
10:03cemerickchouser: you mean if someone is :using the other lib?
10:03cgrandok, I'm going to lobby lpetit to make ccw automaintain (:refer-clojure :only []) :-)
10:04chouserright, isn't that what's causing these problems?
10:04chouser(:use [clojure.contrib.seq :only [reductions]])
10:05cemericksure; I suppose in that case, "local" means "what you use and define wins".
10:06cemerickThat's not going to help someone that :uses two libs that have the same name def'ed, but again, I don't think that's a problem to be solved. Or, it's a social, rather than a technical problem.
10:07chouserso at the repl, it would simply be impossible to define or refer 'reductions' without first removing it from your ns?
10:08cemerickchouser: why does that follow?
10:08chouserwell, how else would you handle it?
10:08defncgrand: (add-classpath "http://github.com/Lau-of-DK/clojureql/raw/master/src/&quot;); github
10:09defncgrand: very cool.
10:09chouseryou're in 'user', user/reductions already exists (points to clojure.core), and now you refer c.c.seq/reductions. what happens?
10:09chouserpreviously, you get a fatal error.
10:10chousercurrently, last one wins (user/reductions starts pointing to c.c.seq/reductions)
10:10cgranddefn: this ugly hack still work?
10:10defncgrand: don't know -- i thought it was a recent post because you don't date your posts you just put the time on it
10:10cemerickbah, I need a pre-last-var-wins repl
10:11defnutilities — cgrand @ 19 h 34 min
10:11cgranddefn: oops
10:11cemerickanyway, yeah, the REPL is a slightly different use-case than whole-file loading. There, last-var-wins probably should hold sway.
10:11cemerickcontrolled by a var set in the REPL, presumably.
10:12defncgrand: will there be a new release of enlive and moustache in the near future for 1.2?
10:13defncgrand: (on clojars)
10:13cemerickchouser: hrm, no, I take that back. last-var-wins is just bad.
10:14cemerickI fiddle around with a fn for a while, get it into just the right condition, and then run a blanket use that clobbers it (and who knows what else?). No thanks.
10:16cemericklast-var-wins changes use from a slightly icky but useful thing, into a dangerous beast. ;-)
10:17cgranddefn: posts have date now (no more need to look at the permalink)
10:18cgrandand I will do releases targetting 1.2 or targetting both 1.1 and 1.2 (I haven't looked at version ranges yet)
10:19defncgrand: awesome. i've been meaning to upgrade to 1.2 for a couple projects but have been holding out for a stable 1.2 release
10:19defncgrand: thanks for the cool tools. :)
10:19eleanam I correct assuming it should do the trick of limiting print level ?: (binding [*print-level* 0] [[1 2] [2]])
10:21chouserhm. Namespace.mappings is already an atom. If it were a ref, most usage could be the same as before, but some situations (like 'load') could run in a transaction.
10:22cemerickchouser: you should turn pro someday. :-)
10:22chouserwithin the transaction, replacing a core mapping with a local def or with a new mapping could be allowed, but replacing a non-core mapping with anything disallowed.
10:22chousercemerick: heh. I have no idea what that means!
10:23cemerickchouser: I've been big on the sports metaphors lately. And, I'm running on little sleep today. :-)
10:23chouserwait, why is a transaction needed?
10:23cemerickchouser: not needed, but using a transaction means that, if a transitive dependency four layers down fails to load, your environment is left in the state it was in before.
10:23chouserwe used to use an atom and fail. we could just do the same, but fail in slightly different circumstances.
10:24chouserwe don't have transitive refer mappings though
10:24chouserthe only think changing your namespace is you.
10:24chouserthing
10:25cemerickYeah, I don't mean for refers, I mean for loads that fail.
10:25chouserloading a lib doesn't change your namespace
10:25chouserso if it fails your namespace is still unchanged.
10:26chouseryou might have been planning on refering some thing when it was done loading, but if it failed you probably shouldn't. :-)
10:27cemerickRight, I know it doesn't impact the current namespace, but load certainly impacts other namespaces. Partially loaded libs have been a source of pain occasionally.
10:27cemerickbut that's a whole separate topic :-)
10:27chouserthis doesn't prevent you from doing something like using a fn from core, then redefining it locally and using that.
10:28cemerickYeah, local defs and :usages should always win.
10:28cemerickhrm
10:29chouserI can't see any way to prevent that without brining in all the pain we're trying to avoid.
10:29cemerickNo, that's fine.
10:29cemerickBut local defs should *always* win, and a conflicting use should fail.
10:30cemericki.e. (def reductions 5) (:use [c.c.seq :only [reductions]]) should error
10:31chousersure, I'm saying (print 123) (def print println) (print 456) would succeed, but the two uses of 'print' would do different things
10:32cemerickyeah, I think I'm OK with that.
10:32cemerickclobbering referred vars is OK -- you can always recover from that. Clobbered local vars are gone forever.
10:33chouserso if partially-loaded libs is a different topic, I think this might be a fairly simple change.
10:33chouserthe question is if everyone (well, the right people) would agree it's desirable.
10:33cemerickheh
10:34cemerickwell, last-var-wins is simply bad. Hat tip to cgrand for the penultimate example.
10:34defnsnapple just fuels my rage
10:35cemerickdefn: crack a chilled diet raspberry, and you'll be as relaxed as can be ;-)
10:36defn:D
10:36chouserthis does special-case 'clojure.core' in a few more places. That used to only be special in the ns macro.
10:36cemerickchouser: does it have to, though?
10:37chouserto do what you've described, yes.
10:37cemerickah, yeah, nevermind
10:38chouserthe alternative would be to allow a later :use to override an earlier one, which would allow cgrand's nightmare.
10:38cemerickyes
10:39cemerickit's everyone's nightmare, actually. We just don't know it yet.
10:39chouserIt's cgrand's because he observed it. :-)
11:35Ploujhi
11:35cemerickholy crap, Array.forEach isn't standard in javascript
11:36cemerickJust thought you'd all like to share in my misery. :-)
11:38raekcemerick: seen http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/ ?
11:38sexpbot"Array.indexOf in Internet Explorer | soledad penadés"
11:39raekI guess js is a pretty neat language, at least outside the web
11:39cemerickraek: yeah, I'm looking for a canonical forEach impl right now
11:40fogusIs is a nice language... the prototypical 20% language... but nice
11:41cemerickDistribution is the *only* thing it has over any other reasonable language.
11:43foguscemerick: That does not sound like a positive
11:43cemerickfogus: oh?
11:45cemerickraek: this looks semi-canonical and fairly complete: http://code.google.com/p/js-methods/
11:45sexpbot"js-methods - Project Hosting on Google Code"
11:45fogusThe only value of the language itself is something that has nothing to do with the language itself. :p
11:45cemerickoh, right
11:45cemerickyeah, I think that's fair, relative to other languages.
11:46cemerickIts only *relative* benefit is distribution; it has some good characteristics, but those are matched or eclipsed by plenty of other langs.
11:46fogusI see
11:47fogusI'm actually excited about coffeescript. I think its symbiotic model, while not ground-breaking, is the wave of the future for js
11:51cemerickjs seems like a really bad host language in general
11:51foguswhy do you say so?
11:53cemerickbaked-in object system...odd equality semantics...boxed everything...poor stdlib...
11:53arohnerI'm excited about clojure-in-clojure-in-js
11:53cemerickdefinitely
11:55cemerickThere must be a good reason for it, but I wonder why an org like mozilla never exposed a lower-level bytecode layer that people could base other language impls on.
11:55foguscemerick: That makes it the perfect host. All of that stuff needs to be fixed and the js language committee isn't going to do it.
11:56cemerickfogus: doesn't that just guarantee poor perf and a miserable life for language implementors forevermore?
11:57fogusMaybe if Eich had and 11th day he could have created a bytecode layer
11:57fogusWell, perf is a problem, but it's the job of the language implementor to be miserable... so I don't have to be (it's all about me)
11:57cemerickheh
11:58arohnerin general though, the web is a terrible place for application development
11:58arohnerand I don't see that getting any better, even if js gets a bytecode layer
11:59cemerickwell, there's places where the lang is bad, and places where the DOM is bad. The latter is solved by jquery et al...the former is solved by having another lang :-)
11:59fogusCrockford said that the browser was the most hostile environment he'd ever seen... until he found out about mobile
11:59arohneryeah, but there's still problems with ML + CSS
11:59cemerickarohner: all sites will soon just be js + canvas. Problem solved! :-D
12:00arohnercemerick: hah. true
12:00arohnerthen we'll just be running X over HTTP, with an order of magnitude more bloat
12:01fogusI shudder thinking about programming for the web. We use GWT and although it's bad, it's way better than the alternative
12:01cemerickI can't bring myself to hack around in java anymore.
12:04fogusMe neither
12:04bsteuberis there a way to specify a specific snapshot-version in maven?
12:05bsteubersay the last pushed jar before the meta-reader-change :)
12:05cemerickbsteuber: yup, just use the concrete snapshot version
12:07bsteuberlike "1.2.0-master-20100426.160114-46" ?
12:07cemerickright
12:07bsteubercool, thx
12:07bsteuberthis will avoid some sleepless nights with swank for now :)
12:07cemerickthe versions plugin will automate this for you if you don't want to muck with them on your own
12:08cemericki.e. it will fix all snapshots to concrete versions
12:08bsteuberI see
12:08cemerickquite key for releasing while depending on a snapshot :-)
12:08bsteuberwill try the simple way at first - but good to know for later research :)
12:09Licenseraloa
12:11joshua-choichouser and fogus: I'm reading your "An In-Depth Look at Clojure Collections" article, and I'm enjoying it a lot
12:15arohnerok, I know I've asked this in the past, but I forgot to actually change the settings
12:15arohnerhow do I get rid of PermGen errors when developing?
12:16chouserfrom where are you getting PermGen errors?
12:16arohnerI'll leave a repl open for a couple of days doing devel work
12:16arohneronly happens on my dev environment, doesn't happen in production
12:17jwr7while we're talking about slime and swank… any idea why I'm getting NullPointerExceptions when doing C-c C-c, while C-x C-e works fine and C-c C-k works fine?
12:17cemerickarohner: turn on concurrent GC, and enable class and perm gen class unloading
12:17arohnerthanks
12:17cemerickarohner: -XX:MaxPermSize=256m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled are my defaults
12:18arohnercemerick: thanks
12:25bsteubercemerick: hm, I think one of my dependencies override the clojure-version so the SNAPSHOT is still taken
12:26bsteuberwill the version plugin help me for this?
12:26cemerickbsteuber: are you declaring the concrete snapshot dep in your pom?
12:27cemerickI mean, in your current project's pom, as opposed to a parent pom...
12:27bsteuberI declare it just once in the parent
12:27bsteuberbut as dependency, not management
12:28cemerickyeah, that should be fine
12:28cemerickput brackets around the version number to force the issue
12:28cemerick[1.2.0-master-dddddd]
12:28bsteuberok, I'll try
12:29cemerickversion numbers are flexible by default, so a -SNAPSHOT version might override a concrete version number.
12:30bsteubercemerick: now I get an error:
12:30bsteuberCouldn't find a version in [1.1.0-alpha-SNAPSHOT, ... 1.2.0-master-SNAPSHOT] to match range [clojure-1.2.0-master-...]
12:31cemerickbsteuber: ok, pull out the brackets, and do.....
12:31Ploujwhat's a good introduction to clojure to read on a train? :)
12:32cemerickbsteuber: mvn dependency:list
12:32LicenserI think maven is kind of borken with dependency ranges :(
12:32cemerickthat'll show us exactly what the dep is resolving to
12:32Licenserit does not enforce then to match
12:32cemerickLicenser: the default is loose, yes. If it weren't you'd be a lot less happy. :-)
12:33Licensercemerick: I have a hard time to belive I could be a lot less happy :P
12:33Licenserat least not today
12:33cemerickLicenser: without flexible version resolution, every one of your project's dependencies would have to, e.g. depend on exactly the same version of log4j, or joda time, or whatever.
12:34bsteubercemerick: ok, I've done that - now I've got a list of stuff I'm using
12:34cemerickbsteuber: right...and what's the clojure dep resolving to?
12:34bsteuberorg.clojure:clojure:jar:1.2.0-master-SNAPSHOT:compile
12:34Licensercemerick: but version ranges and just pick stuff that does not match is a difference
12:35LicenserI know that you can use ranges, and that is great but if maven fetches me a version of clojure and a non matching version of c.c it is just broken
12:35bsteuberso the snapshot, as expected
12:35Licenserat least clojure and clojure.contrib should be very stricktly boundled
12:36cemerickbsteuber: and what's the full error you got before?
12:36bsteuberyou mean with the brackets?
12:36cemerickyeah
12:37hiredmanbrackets and swank?
12:37cemerickyeah, whatever your preferred config would be
12:37bsteubercemerick: Couldn't find a version in [1.1.0-alpha-SNAPSHOT, 1.1.0-master-SNAPSHOT, 1.1.0-new-SNAPSHOT, 1.1.0, 1.2.0-master-SNAPSHOT] to match range [clojure-1.2.0-master-20100323.140115-17,clojure-1.2.0-master-20100323.140115-17]
12:37bsteuber org.clojure:clojure:jar:null
12:38Licenserbsteuber: I am not sure if that will work ike that
12:38Licenserranges have to be numerical,
12:38Licenseras in major.minor.patchset
12:38cemerickbsteuber: yeah, that's not the right version
12:38cemerickshould be [1.2.0-master-ddddddd]
12:38Licenser[1.1,1.2] is a good one
12:39Licenserif you use 3 didgets in a range things usually break
12:39Licenserbsteuber: http://blog.licenser.net/2010/04/22/on-clojure-libs-and-versions
12:39sexpbot"lice! : On clojure libs and versions."
12:40bsteubernow I tried [clojure-1.2.0-master-20100323]
12:40bsteuberbut this gives the same error
12:40cemerickright, "clojure" isn't part of the version number
12:41bsteuberoh
12:41cemerickyou want the entire concrete snapshot version
12:41bsteubermust have sneaken somehow :)
12:41cemerick[1.2.0-master-20100323.140115-17] is probably what you want, given the error msg
12:42bsteuberhm, same problem
12:42bsteuberCouldn't find a version in [1.1.0-alpha-SNAPSHOT, 1.1.0-master-SNAPSHOT, 1.1.0-new-SNAPSHOT, 1.1.0, 1.2.0-master-SNAPSHOT] to match range [1.2.0-master-20100323.140115-17,1.2.0-master-20100323.140115-17]
12:43cemerickI'll give it a shot with another project here.
12:43bsteuberthx
12:45bsteubermaybe I should just install the version as 1.2.0.master-SNAPSHOT and remove the repository reference :)
12:46cemerickbsteuber: OK, I've got the same error :-)
12:48bsteuberok, good to know
12:50bsteubermaybe I should beg technomancy to update the elpa swank-clojure so I can happily use the SNAPSHOT again? :)
13:38technomancybsteuber: as soon as clojure 1.2 does a release candidate.
13:41bsteubertechnomancy: great to hear - so I just have to use some hacks until then :)
13:50technomancyyou don't need the latest swank-clojure.el to use snapshot versions of clojure though
13:51arohnerman, I really want a macro that does to reduce what 'for' did to map
13:51arohnerI just don't know what it would look like
13:52DuneManIs there a more straightforward way to write this (reduce + partition-by??) that doesn't hold the head? http://paste.lisp.org/+24BN
13:52ataggartcouldn't you just reduce the results of for?
13:53DuneMan(this code doesn't hold the head, btw, and it works)
13:54DuneManreduce the results of for...
13:55ataggartmy comment was directed at arohner
13:55DuneManoh, okay
13:55DuneManI was confused :-D
13:55arohnerataggart: I mean a different way of expressing a reduction, that improves readability
13:55arohnerataggart: similar to the way 'for' is a different way of expressing a map
13:56DuneManI am asking because I tried to write it in the naive way yesterday and couldn't come up with something that seemed like it'd work... but then wrapped my head around using lazy-seq with inner and outer recursion and it seems to work.
13:58DuneManmeaning I've shoved 1.7 billion messages through it with no memory leakage.
13:58ataggartarohner: the benefits of for are cartesian product, built-in limits/filters/lets. I can see the value of such for reduce, but I still think it's end up being a for wrapped with a reduce
13:58ataggartduneman: are you trying to make a moving-window average sequence?
13:59DuneManNo. In this case I'm doing sums over a jumping window.
13:59arohnerataggart: I'm mainly talking about how the code gets ugly when you have a large, messy, one-off reduction function
13:59DuneManThe moving-window is simpler.
13:59DuneManbecause you need to keep all intermediate results in memory anyway.
13:59DuneMan"jumping" meaning it outputs 1 result at the end of every period.
14:00arohnerataggart: (reduce (fn [x y] ....) start coll). when that fn gets big, the code is ugly. you can move the fn out to a letfn, but that's ugly as well
14:00arohnerataggart: for me, one of the biggest benefits of for over map is the indention ,and the implicit fn creation
14:01ataggartah because the fn bosy is the body of the for?
14:01ataggart*body
14:01arohneryes
14:01ataggartcool
14:01ataggarthm
14:02ataggartduneman: why not use partition-by?
14:03DuneManI tried to (which is why I asked about it specifically). But was confused about how it was implemented.
14:04DuneManI tried to, but ended up having trouble writing it. Specifically because I need to loop over partitions, updating the 'end time' per partition.
14:05DuneManEither that or move the code that does the date addition into the check...
14:05DuneManthough actually, I suppose my code is slightly wrong
14:05ataggarthard to say without understanding the datastructure you're working with
14:05DuneManbecause 60-second windows will drif.
14:05DuneManataggart: an infinite sequence defined by: (repeatedly #(.take queue))
14:06DuneManin the sequence are somewhat large hash maps.
14:06ataggartheh
14:06ataggartthe elements matter too
14:06DuneManAh, yes.
14:06DuneManSo the elements are discrete events: {name "Blah" :date "Blah" .... parameters .... }
14:06ataggartalso I'n not smart enough to infer what you're trying to do from the code (nor the comment)
14:07DuneManThe code does a reduce per partition. (The inner step function recurses, applying "f" to the result of itself and the next item in the list, just like reduce does)
14:07DuneManand creates a lazy sequence of the results.
14:08ataggartI'm trying to deduce what you're partitioning by
14:08DuneManI feel like I should be able to use partition-by and reduce to make it work.
14:08ataggartI think you shoudl too
14:08DuneManI'm partition by (date< time-of-current-event end-time)
14:08ataggartthese elements aren't already sorted by time?
14:09DuneManYes.
14:09DuneManThey're real-time events, guaranteed to be sorted before they hit any of the processing threads.
14:09DuneManI'm used to writing this kinda code in c++ :-)
14:10DuneManThey *are* already sorted by time.
14:10ataggartk, then I don't understand the variable naming, seems that s-exp you pasted should always yield true
14:10DuneManThe s-expression returns a (lazy-seq
14:10DuneMan*wonders if I posted the write code*
14:10ataggartthis: (date< time-of-current-event end-time
14:10ataggartseems like it would always return true
14:11ataggartwhich I infer means I don't understand what it really means
14:11DuneManno. Check out the function call at the end of the (lazy-seq)
14:11DuneManit calls (step .... (date+ first-event-time length)
14:11DuneManSo, on the first call, you get an end-time in the future
14:11DuneManat the end of each partition, we recurse with a new (future) end time.
14:12DuneManThere's the inner "recur" recursion for calculating the reduce, and then at the end of the partition, I do (cons val (<outer recursion in lazy-seq style)>)
14:13DuneManwhich becomes the result of the current context, and then lazy seq pulls that value off, and executes the next chunk.
14:14DuneManIt's somewhat similar to how take-while works, with an inner recursion loop that looks like reduce.
14:16ataggartso you're reducing the elements that fit within a window of time, then reducing the next window of time, etc?
14:17DuneManyes.
14:18ataggartif the window is, say 60s, shoudl that 60s start from the time of the last element in the previous window, or 60s from the first element in the next window?
14:18DuneManhttp://paste.lisp.org/display/98915#1 <-- better variabler names
14:19ataggartor 60s of real time, regardless of the time values of the elements
14:19DuneManataggart: it should be at 60*<number of partitions processed so far + 1>, ideally.
14:19DuneMan60s as defined by the timestamps.
14:19DuneManMy implementation here does "60s from the first element seen"
14:19ataggartk
14:19ataggartstand by
14:19DuneManwhich is a little wrong.
14:21DuneManI suppose partition-by would work without head holding because it uses two lazy-seqs in the background (take-while...) and (drop-while...)
14:21DuneManI get really confused by what is actually holding onto references.
14:24ataggartwell you can't use partition-by since your predicate doesn't just use the current element
14:24ataggartyour predicate has two variables, the current element time and the max element time for that partition
14:25DuneManYes, and I couldn't find a way to tease that apart.
14:26DuneManThe other option, of course, is to change my predicate
14:26DuneMansuch that it partitions time into n-second multiples by doing a mod.
14:26ataggartwhat's the "start" value supposed to be?
14:27DuneManAh, if you go to my updated post (http://paste.lisp.org/display/98915#1), you'll see I changed its name to "initial"
14:27DuneManit's the initial value of the reduce, e.g. 0.
14:27DuneManstart was a bad name.
14:27nurvHi.
14:27DuneManhi nurv.
14:28nurvHi, DuneMan. :)
14:29DuneManThis is one of those cases where I find it very easy to reason about how to implement this imperatively, but difficult using a functional+seq style approach.
14:29DuneManhoping to get past that soon
14:30ataggartk, I annotated your last paste
14:30DuneMan(The initial value of the reduce at the start of each partition)
14:30DuneManaha! split-with....
14:30ataggart:)
14:31DuneManThat is so the right way of doing this.
14:31ataggartand I messed up the last line
14:31DuneManbut yes, this makes sense.
14:31ataggartfixed it
14:32DuneMansplit-with is what I wanted last night when I used parition-by :-)
14:32DuneManThis is much easier to understand, thanks :-)
14:33ataggartya, since you need to change the values for each window, you can only get one "partition" at a time, hence split-with
14:33ataggartnp
14:34DuneManI know there was something like split-with, but my 3am coding brain couldn't find it
14:34DuneManSo I ended up with what you saw :-)
14:38DuneManAha... this ends up holding the head somewhere
14:38DuneMan*watches memory usage climb*
14:39DuneManyeah, it holds onto the whole list for the length of the time window.
14:39DuneManand then that whole chunk goes away.
14:40DuneManOr it did that for the first 2 minutes... and now it doesnt, so it must not be.
14:41DuneMan*confused*, yes, it working.
14:43DuneManAnd using a baseline of less memory for some reason, with a similar cpu profile. perfect.
14:44bmasonwhen I run 'lein pom' it does not generate a <build> section... I'm wondering why
15:05bmasonany clue on why lein pom wouldn't generate a <build> section?
15:06bmasonI've compared my project.clj with the LabRepl project and I don't see any major differences/sections missing
15:12sidsbmason: as I understand it, the pom generated by lein pom is mainly useful for pushing to maven repos
15:12bmasonI'm trying out the netbeans plugin, and it seems to base the file list on the .pom...
15:13sidsbmason: I don't think labrepl's pom.xml has been generated using lein pom
15:13bmasonyeah, I'm thinking not, since when I erase it and regenerate it using lein it is missing the build section as well
15:14bmasona bit weird though, since the note at the bottom says it was generated by lein
15:15sidsmaybe the pom was generated using lein but then edited and the note was not removed
15:15bmasonyeah
15:15bmasonhmm... netbeans still seems to work fine with the lein generated pom
15:16bmason(on the LabRepl project)
15:16bmasonnot on mine :)
15:17sidsare you sure the plugin is looking at the pom?
15:17bmasonit doesn't detect it as a project at all without a pom in the directory
15:20bmasonalright, probably time to read up on Enclojure docs
15:41Borkdude,Q
15:41clojurebot<-nil-<
15:43Borkdude,(type Q)
15:43clojurebotclojure.lang.PersistentQueue
15:46hiredman,(conj Q 1 2 3 4)
15:46clojurebot<-(1 2 3 4)-<
15:47chouser,(conj Q (symbol " "))
15:47clojurebot<-( )-<
15:47chouser,(conj Q (symbol ""))
15:47clojurebot<-()-<
15:48Borkdudewhat was the print method again?
15:48chouser,(pop (conj Q 1))
15:48clojurebot<-nil-<
15:55Borkdude,(conj Q (symbol "^_^"))
15:55clojurebot<-(^_^)-<
15:55BorkdudeJonah...
15:59DuneManokay! Now another question, earlier, ataggart helped me come up with a function that partitions a sequence and reduces per partition. I wanted to modify this a bit to change the partitioning
15:59DuneManhttp://paste.lisp.org/+24BW
15:59DuneManThe problem is that this holds the head somehow that I don't really understand.
16:00DuneManoh... maybe I should just...
16:00ataggartthe arity jump
16:00ataggartwould be my guess
16:01ataggartthe call to the 4-arg holds the head then calls the 5-arg
16:01hiredmanor either of the lets
16:02ataggartlazy-seq is a macro but youre not actually calling cons in the 4arg version
16:02hiredmanI would suspect the lets more than the arity jumps
16:02DuneManExactly. So I could get around this by having a a macro that expands the function.
16:02hiredmanno
16:02DuneManexpands to the function call
16:02hiredmanno
16:02hiredmanno
16:02DuneManso that I don't have to pass in the "date-end" arg
16:02hiredmanstop flailing around
16:02hiredmanstop looking for "magic"
16:02ataggartsigh
16:02hiredmanlazy-seq is not magic, so don't just stick it anywhere
16:03DuneManok.
16:03hiredman,(macroexpand '(when-let [a foo] bar))
16:03clojurebot(let* [temp__4810__auto__ foo] (clojure.core/when temp__4810__auto__ (clojure.core/let [a temp__4810__auto__] bar)))
16:03hiredman^-
16:04hiredmanit kind of depends I guess
16:04hiredmanit seems like the locals clearing should be able to handle that
16:04hiredmanbut I am unsure
16:05DuneManWith just a normal function call inside the 3-arg version that calls the 4-arg version?
16:06DuneManthus the whole thing returning a lazy seq?
16:06hiredmanDuneMan: tell me why you are calling lazy-seq in the four arg version
16:07hiredmanif you don't understand what it does, you should not be doing it
16:10DuneManBecause I need the result to be a sequence of values resulting from a reduce on subsequent partitions. Similar to partition-by. I want to be able to treat the result as a sequence of reductions.
16:10hiredmanwhat does that have to do with the call to lazy-seq in the four arg version?
16:10hiredman(the answer is nothing)
16:14DuneManI guess that is what I need to figure out exactly, my current intuition is that since each s expression isn't at all evaluated until it is requested, you can effectively make the calls to subsequent parts of the expression not hold onto a reference.
16:15hiredmanhttp://paste.lisp.org/display/98924#1
16:15DuneManIs that wrong?
16:16hiredmanyes
16:16hiredmanclojure is not lazily evaluated
16:16DuneManlazy-seq's documentation says explicitly that's what it does
16:17DuneMan"Each coll expr is not evaluated until it is needed."
16:17hiredmansure
16:17hiredmanif you are making a correct call to lazy-seq
16:17hiredmanbut lazy-seq is not all of clojure
16:18hiredmanyou could have said "in a lazy-seq my current intuition is ..."
16:18hiredmanand laziness has nothing to do with whether or not you hold on to the head
16:19hiredmanit just gives you more rope to hang yourself with if you do
16:19DuneManThat is what I meant, I was speaking in the context of your question about why it has the (lazy-seq...) calls.
16:19DuneManSorry I wasn't more clear about that.
16:19hiredman,(doc lazy-seq)
16:19clojurebot"([& body]); Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls."
16:19hiredmanDuneMan: so all the four arg version does is call the five arg version
16:20hiredmanso it will return what the five arg does
16:20hiredmanand the five arg returns a lazy-seq
16:20hiredmanso you effectively have (lazy-seq (lazy-seq ...))
16:20hiredman0
16:21DuneManSo, the take-while and drop-while bit is exactly what split-with, does, correct? So the problem then with the 5-arg version of what I posted was the let binding?
16:21hiredmanthis kind of think leads me to believe you don't know what you are doing and should be using lazy-seq
16:21DuneMan(and the 4-arg version was wrong)
16:21hiredmanthing
16:21hiredmanand should not be
16:22hiredman:)
16:22DuneManNo, I should be doing this, and thus learning how it works.
16:22DuneManIt's sorta like learning how to fight by getting your ass kicked.
16:22hiredmannah, you should be using map + partition
16:22DuneManI tried that, and failed.
16:23hiredmanreally? lets see it
16:23DuneMan*does a git diff*
16:23hiredmanif you find yourself using the lazy-seq macro in preference to map/filter/reduce/etc that is a red flag
16:24DuneManaaand I apparently didn't commit that. So, my initial attempt was "Okay, I can do this with reduce and partition-by"
16:26DuneManThe problematic part was that I need to update my partition-end-time after each partition. Basically, I need to know "How much time has passed". Which now that I think about it means that I can just close over the "start time" of the partition and check whether (< (- current start-time) length)
16:26DuneManand then partition-by will work
16:26DuneManbecause it will only depend on the input of the current item.
16:28DuneManokay, I'll go try to write this with reduce + partition-by, again.
16:28hiredmanare you sure you want reduce?
16:28hiredmanwhat you have there is a map
16:29hiredman(a map of a reduce)
16:29hiredman(map (partial reduce some-fn) (partition-with what-ever something))
16:29DuneManI want to partition a sequence, reducing each partition as its generated.
16:29hiredmana map of a reduce
16:30DuneMan... indeed.... *blinks*
16:30hiredmanyou are mapping a reducing function across a sequence of sequences
16:30DuneManYou are very right.
16:30hiredman~hiredman
16:30clojurebothiredman is lazy
16:32DuneManHowever, I see a problem with writing the partitioning function (what-ever in your example)
16:33DuneManBecause, at least how I've thought of this, it is not always the same function, it changes depending on the number of sequences seen.
16:34hiredmanif you cannot get by with the sequence combinators provided for you, then you should consider constructing your own
16:34hiredmanbut don't try and cram everything into yours
16:34hiredmanif in this case you just need a custom partitioner, then just write that
16:34hiredmanand use (map (partial reduce some-fn) ...) across that
16:35DuneManright, so I could use the split-with technique to return the partitions, and then map my reducer over that.
16:35DuneMancorrect?
16:40ataggartsigh
16:42ataggartagain, you cannot use partition-by because the predicate function requires is multivariate
16:43DuneManright, and thus the split-with technique to produce my partitions.
16:43ataggartyup
16:44ataggartso I'm still at a loss as to hiredman's point
16:44ataggartwhich isn't unusual
16:44DuneManWell, he is pointing out that I don't quite understand what I'm doing.
16:44DuneManand he is right.
16:44ataggartwhich is both obvious and unhelpful
16:45ataggartif you knew what you were doing you wouldnt be asking for help
16:47ataggartand nothing I've seen so far addresses the holding-on-to-head issue
16:47DuneManthat is true, heh. He did point out a very good thing, though, which is that I can split this up into two logical steps of "map the reducer over a sequence" and "make a partitioner that generates a sequence"
16:47ataggartyup
16:48ataggartthough it doesn't solve your problem
16:49DuneManataggart: True.... and I still don't quite understand when things are holding on to the head.... not intuitive to me yet.
16:49DuneManHoping to gain that in time.
16:49ataggartI'm still not clear on why you think you need the init value
16:51ataggartyou only need 3 args, the reducing fn, the time window, and the seq
16:51DuneManataggart: Well, a reduce can start with "0" if its doing a simple count, but if I want to do what "frequencies" does (ie return a hash-map of keys to frequencies) then I would need to init it with {}
16:52DuneManexactly the same reason "reduce" takes an init value.
16:52ataggartk, I missed that the same initial is used for every call
16:53DuneManah, yes.
16:53ataggarterm, every reduce
16:53DuneMansame initial is used for each reduce
16:53ataggartbut yeah, split out the custom partitioning
16:54ataggartthen you can do whatever
16:54DuneManMaybe it will make it easier to reason about.
16:54ataggartusing extant functions
16:54ataggartyup
16:54ataggartstill odd about the head-holding
16:55DuneManI'll split it out, and try again and see if I can pin down what's happening. Thanks for the help and understanding :-)
17:13springifyGood evening everybody. Is there a way to make slime use the clojure version in the project's lib directory when connecting to a session started with lein swank?
17:14springify(Mine seems to insist on using the one in ~/.swank-clojure
17:30RaynesIs there some sort of magic that must be done that I don't know about in order to get hiccup's include-css to find a css file?
17:33springifyHmm, doesn't include-css only render the html? Won't you still need to configure the ring middleware for serving static files?
17:34RaynesUh, I don't know.
17:35RaynesIt seems to serve the page.
17:35RaynesBut it looks like the css file is just non-existent. I don't know if I'm supposed to link to it in some special way or something.
17:35RaynesI'm completely new to this stuff.
17:35DuneManinterestingly enough, when I split out my partition and functions and reduce, I get a memory usage pattern that implies that the time window is being held on to, and then at the end of the period, it is reduced and all the data goes away. then it repeats.
17:35springifyRaynes: You need to wrap your handler with the middleware for serving files.
17:35DuneManSo... half way there.
17:36springifyRaynes: Do a (find-doc "wrap-file")
17:36springifyRaynes: Wrap your application, that is...
17:37springifyLet me see whether I find an example.
17:38Raynesspringify: That worked.
17:38Raynesspringify: Thanks a lot man. :D
17:39springifyRaynes: You're welcome. The doc for ring is actually okay. There's a small example showing the wrap-* stuff, too.
17:40RaynesIt would probably help if I had even a slight idea of what I was doing.
17:40RaynesI'm getting there.
17:40RaynesI think. ;)
17:40springifyNow who can tell me how to work around the "could not find gem cucumber..." error when using cuke4duke with lein-cuke?
17:43dakronecan anyone tell me what's I'm doing wrong with protocols here: http://gist.github.com/394035 ?
17:52springifyIs there a way to make slime use the clojure version in the project's lib directory when connecting to a session started with lein swank? Mine seems to insist on using the jars in ~/.swank-clojure.
18:01lancepantzso what would be the right way to overload a method in DynamicClassLoader?
18:01lancepantzcan i do that from within clojure using proxy?
18:09technomancyspringify: use M-x slime-connect instead of M-x slime
18:11springifytechnomancy: Great, thank you. Manually updating .swank-clojure every time I wanted to try out a different version seemed cumbersome :)
18:16eleanwhy memoization works only for 144 consecutive recursive calls ?
19:01DuneManataggart: I think I've figured it out.
19:06sbtI want to specify a custom string representation for a struct I've defined. is there a standard way of doing this?
19:29ataggartsbt: (defmethod print-method ::my-type [x writer] (do-stuff...))
19:29ataggartsee http://clojure.org/multimethods
19:34DuneManataggart: I think the problem with *any* lazy seq with a body that looks like (cons (take-while.... s) (.... (drop-while ... s))) is that the whole size of the partition will necessarily be realized and in memory at once, until you've finished reading it.
19:34hiredmannope
19:34DuneManBecause the (drop...) has to hold onto the head of its sequence.
19:34hiredmannope
19:34DuneManHow does that get executed, then?
19:34ataggartuseful response as always
19:35DuneManBecause that is exactly the behavior I am seeing, hiredman.
19:35hiredman~def drop
19:35hiredmanbah
19:35DuneManIt consumes a partition, stores it in memory, and then once that whole partition has been consumed, it it goes away at once.
19:36DuneManonce per window-period (minute).
19:42DuneManhttp://paste.lisp.org/+24C7 <-- so, this is how I split up the partition and reduce phases.
20:07DuneManso, then, hiredman... if I am wrong about how this works, can you explain to me how partition-by manages to cons together the items from a partition, place this whole list on the front of another list then then does a "count" on the first list in order to force it to consume elements... without keeping the entire partition in memory between the execution of the first statement and the count?
20:07DuneManhttp://github.com/richhickey/clojure/blob/ab6fc90d56bfb3b969ed84058e1b3a4b30faa400/src/clj/clojure/core.clj#L3429
20:08DuneManit does (drop (count run) s)
20:10joshua-choiI just git-pulled Clojure 1.2 again, and I'm happy to see that pprint was recently promoted
20:22DuneManConcerning partition-by, it looks to me like we have exactly 2 things consuming elements from the head of the list [a (take-while ... s), and a (drop n s)], and these are run sequentially. Hence, the a reference to the head of the list must exist until the 2nd item [the drop] starts consuming it. Thus, the entire contents consumed by the first one will be in memory until it stops consuming, and the 2nd item starts consuming. Thus partition-by is inefficien
20:22DuneManthe size of your partitions is big.
20:24DuneManAm I wrong? And if so, how, and why am I seeing the behavior I would expect if that were the case.
20:24tomojtake-while doesn't consume anything, does it?
20:24tomojnor drop?
20:25tomoj,(let [x (drop 3 (iterate inc 1))] (println "foo"))
20:25clojurebotfoo
20:25tomojguess I just don't know what you mean
20:29tomojoh, I see
20:36tomojDuneMan: https://gist.github.com/12c68e4e194f2477313d
20:36tomojdoes that work any better?
20:39tomojI got a 5x speedup on some stupid test case
20:40DuneMan*takes a look*
20:42DuneManAh, that is actually how I had this implemented. And it indeed exhibits the behavior that I described above. some few hundred megs of data is read in during the minute window, and at the end of it, the partition is reduced, and the memory is freed.
20:43DuneMansplit-with just gives you (take-while...) (drop-while...), so you end up with the same effect, a take consuming a bunch of data starting from head, then the drop consuming a bunch of data starting from head.
20:43tomojI don't really have a clue what that means, good luck
20:43tomoj
20:43mmarczykum, I might have missed a fragment of the conversation
20:43tomojdouble-spacing on paste.lisp.org too, must be your client
20:44mmarczykbut tomoj: it looks like you're using partition-by inside partition-by* ?
20:44tomojoh, whoops
20:44tomojthat should've been changed
20:44DuneManIt means that if I am reading in 500mb of data per minute, the whole 500mb is stored in memory, even if it doesn't need to be.
20:44DuneManI'm copy/pasting from terminal... and... when I look at paste.lisp.org its not double-spaced...
20:45tomojhere? http://paste.lisp.org/display/98935
20:45tomojthat doesn't look totally fucked up?
20:45DuneMannope.
20:45tomojoh, I bet it's because my screen is too small
20:46bmasonlooks hard wrapped to me
20:46bmasonprobably there are endlines where there shouldn't be?
20:47tomojthe raw source looks fine
20:47mmarczykDuneMan: is there any chance that, in processing your data, you might need to skip one partition ahead, then go back?
20:47tomojit's just that most of the lines are very very long with a bunch of extra whitespace
20:47DuneManmmarczyk: No.
20:47mmarczykthen why would you use partition-by in the first place?
20:47remleduffWhy does when-let only allow 2 args, and not as many pairs as you might want to give it?
20:48DuneManmmarczyk: I'm not using partition-by, I'm writing a partition function that does something similar. I need to generate partitions, and then reduce each of them. And I never want all of the data stored in memory.
20:48DuneManbecause since each partition is being reduced, they don't need to be.
20:48tomojremleduff: what would you want it do if you gave it more? only proceed if all the values were truthy? proceed if any one of them were truthy?
20:48technomancyremleduff: because it's not obvious what the semantics would be for multiple bindings
20:48technomancyremleduff: and vs or
20:48DuneManer it doesn't need to be*
20:48tomoj..yeah, what he said
20:49DuneManThe partitions are defined on by slices of time, and the input is guaranteed sorted by time.
20:50mmarczykthat sounds like a job for reduce to me
20:50mmarczykmeaning an "outer reduce", with "per-partition reduce" happening inside
20:50remleduffBut doing (when-let [a (foo)] (when-let [b (bar)] [a b])) just seems kind of grotty
20:51remleduffOnly makes sense for "and"
20:51DuneManmmarczyk: It is (map (partial reduce f initial) (generate-partition-stream .... s))
20:51DuneManAs pointed out by hiredman
20:52bmasonanyone out there using JSwat with slime?
20:53DuneManSo, while investigating that, I encountered all sorts of ways to do this that realizes each partition in memory at some point. And it seems that partition-by, and the ilk, all do that.
20:53DuneManAnd I am hoping to find out whether my reasoning is correct.
20:54mmarczykwell I'm pretty sure it is
20:54mmarczykfor the reasons you've pointed out above
20:54DuneManawesome! Given that, I think my initial, slightly screwy solution, is the correct one.
20:55mmarczykI think it would be a bit of a pain to write a partitioner matching your specs
20:55mmarczykhave you managed to write one...?
20:56DuneManI managed to do it by combing the reduction and partitioning.
20:56DuneManhttp://paste.lisp.org/display/98924#1
20:56mmarczykright, that's my initial idea -- "outer reduce" :-)
20:56DuneManThis works because there is only 1 thing that actually consumes the sequence.
20:56mmarczykyup
20:57DuneManWell, then hiredman lead me astray... oh well, learned a lot.
20:57DuneManmaybe I was explaining myself poorly.
20:57mmarczykum, not necessarily
20:58mmarczykI mean I still believe that it's possible to write a "nicer" (lazier) partitioner
20:58DuneManer, sorry
20:58DuneManthat links was the wrong one.
20:59mmarczykwhich version of Clojure are you on, by the way?
21:00DuneManoh, I see, they give different urls for the same post.
21:00DuneManI am on 1.2
21:00DuneManWhich helped a ton compared to 1.1
21:00DuneManmmarczyk: I may try to write a nicer lazy partitioner right now.
21:01mmarczykDuneMan: I think I might try my hand too :-)
21:01mmarczyk(unless I fall dead straight into my bed, which might happen... it's been a long day)
21:01DuneManI think the strategy with the inner recursive function is a good one... there's some library code which does similar.
21:01mmarczyk(but I'd hate not to have some fun at the end of it :-))
21:25mmarczykok, I think I've got something for you
21:26mmarczykthat's just about the weirdest code I've written in Clojure
21:26mmarczykjust let me Gist it...
21:27mmarczykhttp://gist.github.com/394219
21:28mmarczykthis is a partition-by which goes out of its way to discard everything that won't be needed any more
21:29mmarczykon the other hand, it simply won't work as written if you don't force each individual partition in full before moving on to the next one
21:32mmarczyk(and there are bugs, not surprisingly, ouch... hopefully fixable)
21:48DuneMan*takes a look*
21:49DuneManyes, each partition is necessarily fully eaten
21:52DuneManI see... you use an atom...
21:53DuneManthat is really... funky...
21:54DuneMandon't quite grok yet :-)
21:55DuneManso you use an atom to keep track of the head in the state of the inner function
21:56tomojthat sounds funky indeed
21:56DuneManIt is, incidentally, quite similar to what my co-worker was suggesting a bit ago.
21:56slyphonis there some common bit of documentation people have been working off of to grok deftype et. al.?
21:57tomojI assume you mean beyond the docstrings?
21:57slyphonyeah
21:57tomojI'd been looking for something like that for a long time
21:58slyphonusually there's some blog post out there that shows "Hey, here's an example"
21:58slyphonoh, shoot
21:58tomojthe only other thing I ever really looked at was http://www.assembla.com/wiki/show/clojure/Datatypes
21:58sexpbot"Datatypes | Clojure | Assembla"
21:59mmarczykDuneMan: not only is it funky, it doesn't really work! ;-)
21:59slyphontomoj: ah, this is good
21:59slyphonty
21:59tomoj,'`'foo
21:59clojurebot(clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote sandbox/foo))))
21:59tomojanyone understand that?
22:00tomojI can sort of make sense of the result but I don't really understand why it's the result
22:00DuneManNo :-)
22:00slyphonyou're doing some major evil w/ escaping
22:00mmarczykDuneMan: but hopefully it's fixable
22:00tomojI'm only doing that evil because I want to understand it
22:00slyphonlike ~'blah in a macro
22:00tomojI don't have anything like that in actual code
22:00DuneManmmarczyk: hah. I'm still trying to do it without an atom... feeling... um... yeah.
22:00slyphontomoj: thank god!
22:00tomoj:D
22:01slyphontomoj: i mean, #perl is ----> that way
22:01slyphon;)
22:01mmarczykDuneMan: you could try using deftype with a :volatile-mutable field, maybe?
22:02mmarczykDuneMan: but to me this feels even more like a vortex of utter weirdness
22:02mmarczykI mean, the atom-based approach is just a tiny vortex of utter weirdness
22:04mmarczyktomoj: have a look at SyntaxQuoteReader in clojure.lang.LispReader maybe :-)
22:04DuneManMy solution of shoving the reduce and partition together is looking pretty damn good
22:04mmarczykDuneMan: a single reduction is always going to "just work"
22:04mmarczykno question about that
22:05mmarczykit could be nice to have a special-purpose partitioner to do some of that work
22:05mmarczykthough
22:05DuneManAgreed.
22:05DuneManespecially considering ... I will be doing things 'like this' again
22:06tomojmmarczyk: thanks
22:06mmarczyknp
22:06mmarczykDuneMan: exactly
22:07DuneManI like how what I needed to do fell directly into this corner-case of stuff that the clojure standard lib just doesn't do very nicely.
22:08slyphon"just lucky, i guess"
22:08slyphon;)
22:08DuneManIf only I could hold 1.5tb of data in memory at once...
22:08tomojoh, I get it
22:09tomoj'`'foo is '`(quote foo)
22:10mmarczyktheoretically `(quote foo) could just return (quote *ns*-name/foo)
22:11tomojdoesn't it?
22:11tomoj,`(quote foo)
22:11clojurebot(quote sandbox/foo)
22:11mmarczykrather than that unearthly bundle of seq-manipulating functions :-)
22:11mmarczykwell in one sense it does, in another it apparently doesn't
22:11tomojwell, it expansd to the unearthly bundle I guess
22:11mmarczykho-hum :-)
22:12mmarczykI like how helpful my previous full sentence was :-)
22:12tomojand the unearthly bundle, when eval'd, returns (quote ns/foo)
22:12mmarczykyup
22:13mmarczykit's actually somewhat unusual of Clojure
22:13mmarczykthe fact that syntax-quote is not called quasiquote :-P
22:13mmarczykand also, it is not a macro
22:13tomojdo you really think there is another possibility?
22:13mmarczykwith a reader macro as a shorthand notation
22:13tomojI mean, that syntax-quote could work without expanding to unearthly bundles?
22:13tomojI'd be surprised if rich did that for no reason
22:13hiredmanChousuke tried to write it as a macro but I don't think he got it fully functional
22:13mmarczykin Scheme, quasiquote can be implemented as a macro -- and that's the way people do it
22:14mmarczykof course it's not the same thing
22:14mmarczykwhich is another part of how unusual s-q is
22:15mmarczykhiredman: interesting
22:16tomoj,(eval (eval (eval ````foo)))
22:16clojurebotDENIED
22:16tomojoh, duh
22:16mmarczykanyway, I thought syntax-quote-as-a-macro was a vague plan for the future?
22:17tomojI don't see how you could do it without unearthly bundles
22:17mmarczykas a macro, you couldn't :-)
22:18mmarczykbut then you'd get '`'foo -> (syntax-quote (quote foo))
22:18mmarczykbecause `'foo would not be mangled by the reader
22:18tomojah, I see
22:34Ploujanyone here program clojure in Fedora?
22:34PloujI'm wondering what's a good way to setup emacs for repl
22:35tomojonce you have emacs I don't think it matters which distro you're using
22:35slyphonhttp://technomancy.us/126
22:35sexpbot"in which are found tricks of the trade concerning clojure authorship - Technomancy"
22:35tomojI think that's outdated, isn't it?
22:36slyphonoh
22:36slyphonyeah :/
22:36slyphonsorry, i know i bookmarked something
22:36tomojinstall package.el -> install clojure-mode and swank-clojure -> done
22:36Ploujtomoj: well, it's still a matter of whether or not to use slime and stuff and how to get all these emacs add-ons
22:36tomojyeah
22:37tomojdo you already have slime installed and/or need to work with another lisp?
22:37Ploujhumm, I'll try package.el
22:37PloujI don't have slime installed ATM
22:37tomojif you install clojure-mode and swank-clojure from elpa, you'll get enough slime to work with clojure
22:37Ploujk
22:37Ploujslime just sounds cool :)
22:37tomojI also recommend installing the paredit beta
22:37tomojhttp://mumble.net/~campbell/emacs/paredit-beta.el that one
22:39tomojand then something like https://gist.github.com/28fb1aa24fcbe06e25ca
22:39tomoj(paredit is really totally optional)
22:40tomojif you're working on a leiningen project, 'lein swank' and then M-x slime-connect and you should be good
22:40slyphon!!
22:40slyphonparedit is *mandatory*
22:40slyphon...unless you like not being awesome
22:40tomojheh, yeah
22:41hugodtomoj: did you get jclouds doing what you wanted?
22:43tomojnot really, but I worked around it
22:43YmmotPlouj if you're trying to get slime-clojure + emacs, ignore most of the stuff you find on the internet
22:43tomojthe stuff I am interested in writing doesn't depend on the clojure stuff that is already there, so
22:43YmmotMost of it is outdated
22:44slyphonwow
22:44slyphondeftype
22:45Ploujboo, errors installing clojure-mode and swank-clojure: http://fpaste.org/Iz47/
22:45tomojyou can probably ignore the errors
22:45tomojtry `M-x slime` to see if it worked
22:45YmmotLa ligne est mince entre la raison et la névrose n'est pas clairement établi, et je jupe à la limite toutes les heures de veille.
22:45Ploujeven if it says "Cannot open load file: slime"
22:45tomojit should ask if you want to install clojure, say yes
22:45slyphonyeah
22:45Ymmotwhoops
22:46slyphonemacs always throws a ton of errors when compiling
22:46tomojthen `,quit` to kill that repl, use M-x slime-connect instead of M-x slime for real development
22:47Ploujtomoj: ok, that seemed to work
22:47slyphonor swank-clojure-project
22:47tomojswank-clojure-project is dying
22:47Ploujlol, where am I connecting?? :)
22:47slyphontomoj: !
22:47tomojyou need to start up a swank server in your project first
22:47Ploujnothing on localhost
22:47Ploujoh
22:48YmmotOne thing I had trouble with Plouj was make sure you don't already have ~/.clojure and ~/.clojure-contrib directories when you install swank-clojure/slime etc
22:48slyphontomoj: i need it for one of my projects, the classloader does stupid stuff when i run it as a separate process
22:48tomojfor a leiningen project that's `lein swank` in the root of the project, but you may need to add some deps for that to work
22:48tomojslyphon: strange..
22:48tomojwell I think it will stay around but just be deprecated and unsupported
22:48slyphontomoj: yeah, it was java badness
22:49slyphonAtomikos TransactionEssentials being "smart" and "clever"
22:49tomoj"Even if it's deprecated, I will definitely leave M-x swank-clojure-project around"
22:49PloujYmmot: ok, doesn't seem to be the case for me
22:51slyphonsooo, deftype creates something that's like multimethods in the namespace they're defined in?
22:51Ploujtomoj: well, then M-x slime is what I need if I just want to play around without working on any project, right?
22:52tomojyeah, that should work fine
22:52slyphonwow, that's bizarre
22:52slyphonand for some reason reminds me of CLOS
22:52tomojI don't think they're like multimethods
22:52tomojI think they're just java methods?
22:52slyphonwell, it's a dispatch based on type
22:52hiredmanno
22:52slyphonno?
22:52hiredmanthats protocols
22:52slyphonhttp://clojure.org/protocols
22:53slyphonthe (deftype Foo ...) is what i'm looking at
22:53hiredmanyou can implement a protocol inline on a deftype
22:53hiredmanright
22:54slyphonwhat's 'x' in those examples
22:54hiredmanand you are ignoring the protocol stuff that comes *right* before what you are looking at
22:54slyphoni just looked up
22:54slyphonand saw it
22:54slyphon:/
22:54hiredmanwell, I think the assumed reading direction in the clojure docs is top to bottom
22:55slyphon...
22:55hiredmanbut I guess you could complain about the poor quality of the docs and ask for a warning at the bottom to start from the top
22:55hiredman:)
22:56slyphonok ok
22:56tomojam I wrong that you have to call deftype methods like (.foo x) instead of (foo x) ?
22:56slyphoni wasn't sure what was defining the (bar-me ...)
22:57hiredmanI wonder if there is a test suite for syntax-quote
22:57slyphonso 'x' there is 'this'
22:57hiredmantomoj: you wouldn't call like that
22:57hiredmanyou would use a protocol fn
22:58tomojif the deftype implements an interface defining a foo method, then, (.foo x)?
22:58tomojinstead of a protocol I mean
22:59hiredmanyeah
22:59tomojI hadn't realized protocols let you drop the .
23:00hiredmanyou can have your deftype implement an interface
23:00hiredmanthen make a protocol and extend it to that interface
23:01hiredmanand no more .
23:01slyphonoooooh
23:01slyphonthat hawt
23:01slyphoner, "that's hawt", even
23:04manuel_hi
23:04hiredmantechnomancy was talking about once ILookup (what keywords use for looking themselves up in maps) is replaced with a protocol extending ILookup to Number so stuff like (:days 2) would give you the number of seconds in two days
23:06slyphonoh nice
23:06hiredman(extend-type Number ILookup (val-at [n k] ...))
23:06hiredmansomething like that
23:07slyphonhiredman: i did something simple that lets you do (-> 2 days from-now) or (-> 3 hours ago)
23:07hiredmanthat reads well
23:07slyphonyeah, i thought so
23:07slyphonit's embarrasingly easy
23:07hiredmanvery extendable too
23:08slyphonhang on, i'll gist the code
23:08tomojhah, (-> 3 hours ago) is brilliant
23:08slyphoni got the idea from rails' 3.hours.ago sugar
23:09tomojyeah, but your sugar is sweeter
23:09slyphonthat's what all the girls say....
23:09slyphon;)
23:09tomoj(-> 10 minutes and 20 seconds after midnight last Thursday)
23:10tomojthat would be terrible..
23:10slyphonhttps://gist.github.com/5b80f2242f719fca5a07
23:10slyphonhaha
23:10slyphonoh, duh
23:10hiredmantomoj: wouldn't work
23:10hiredman20 is not callable as a fn
23:11tomojaww
23:11hiredman(-> 10 minutes (plus (-> 20 seconds)) after midnight last Thursday)
23:11manuel_are there some "commercial" webapps running on clojure?
23:12manuel_i've been using lisp for that for the last 6 years but i'm thinking of switching
23:12manuel_but i'm wary because of the lack of frameworks and documentation
23:12slyphonyou could also do (-> 5 megabytes)
23:12slyphon(and other such unit conversions)
23:12hiredmanit seems like most companies have clojure in the backend somewhere and rails or similiar on the front
23:13slyphonyeah, that's what we're doing
23:13manuel_i don't really want to delve into ruby :]
23:13rhudsonmanuel_: Flightcaster seems to be the Clojure poster child for webapps
23:13manuel_i don't have the time rather
23:13manuel_flightcaster, k
23:14manuel_the webpart is rails though
23:14hiredmanright
23:14slyphonrhudson: is that the one in Cambridge?
23:14manuel_i have no real backend part
23:14rhudsonnothing's perfect
23:14manuel_anyway, i'll stay with lisp i guess
23:15rhudsonslyphon: Don't know where they're located
23:15manuel_and move my cnc stuff over to clojure first
23:15manuel_thx people
23:15slyphonsure
23:15slyphoncnc? command-n-control?
23:15DuneMan*stares at a memory graph and wonders wth the jvm is doing*
23:15manuel_computer numeric control
23:15slyphonah
23:15manuel_milling machine and laser cutter
23:15slyphonOOOOH
23:15slyphon:)
23:15slyphonfun!
23:16Ploujhumm, how would I compile/eval the ants.clj file I just loaded in emacs with slime. This says http://riddell.us/ClojureWithEmacsSlimeSwankOnUbuntu.html I should do C-c C-k, which does nothing for me
23:16sexpbot"ClojureWithEmacsSlimeSwankOnUbuntu"
23:16PloujC-c C-k is undefined
23:16DuneManconcurrent mark and sweep GC turned on, and I still get this really odd spikes of growth with different slopes. Must be trying to figure out what to do :-)
23:16PloujI didn't actually follow those ubuntu installation steps
23:16manuel_slyphon: "kind of" ;]
23:16slyphonmanuel_: hahaha
23:16slyphonmanuel_: dude, you have frikkin lasers!
23:17manuel_i ripped one out of a dvd-rw
23:17manuel_and put it on a plotter
23:17slyphonhahahahaha
23:17manuel_now i can cut cardboard and foam
23:17slyphonwow, seriously?
23:17manuel_yeah
23:17manuel_got an old plotter off ebay
23:17slyphondaaaamn
23:17hiredmanPlouj: well, if you didn't follow part of the instructions, why do you expect a different part of the instructions to work?
23:17manuel_better than getting a co2 laser for xxx$
23:17slyphoni didn't know a dvdrw's laser wsa powerful enough :)
23:18Ploujhiredman: well, I installed slime and swank with Emacs' package.el thing
23:18manuel_me neither
23:18manuel_it's not perfect though
23:18DuneManyou controlling it with clojure?
23:18DuneManheh
23:18manuel_no, with lisp
23:18Ploujhiredman: I'm just guessing at keys to eval things from buffers
23:18DuneManfair
23:18manuel_but i'm getting tired of deploying lisp apps
23:18tomojPlouj: http://github.com/technomancy/swank-clojure
23:18tomojsome handy keys referenced there
23:19hiredmanPlouj: C-c C-k is the correct keybinding
23:19hiredmanI suggest you follow some directions
23:19tomojdon't follow those directions though, imo
23:19hiredmanbecause it sounds like you now have your emacs in some kind of indeterminate state which may make it harder once you start to try and follow directions
23:21Ploujhumm
23:21Ploujwell, the swank doc says C-c C-k is also correct
23:21Ploujbut my emacs says it's undefined
23:21hiredmanwell, find some directions
23:21Ploujand C-e C-x does something partially (shows code in a mini-buffer)
23:22mmarczykDuneMan: I'll continue on weird partitioning schemes next time I'm awake :-)
23:22mmarczykmaybe you'll have the problem solved by then, in which case it would be nice to compare notes
23:22tomojPlouj: what mode is your buffer in
23:23DuneManmmarczyk: Thanks, I will too. I gave up for now and went with my reducer that I've got
23:23Ploujtomoj: it says ant.clj is in (Clojure)---------
23:23DuneManand moved on to inserting shit huge swaths of data into mongodb
23:23DuneManworks like a charm :-)
23:23mmarczykright :-)
23:23tomojit needs to be in slime mode as well
23:23tomojM-x slime-mode
23:23mmarczyksee you
23:23hiredmanPlouj: my understanding is either the slime or swank you get from the package is bogus for clojure (it's for common lisp) so you either need to reconfigure it for clojure, or delete it and follow the directions in the swank-clojure README
23:23tomojsometimes I have to do this manually when working on a remote emacs, so I'm guessing there's some configuration which makes this happen automatically
23:24Ploujtomoj: ah, now C-c C-k says not connected, although I have slime running in a diff buffer :(
23:24tomojand the repl in that buffer works?
23:24Plouj(I started slime with M-x slime)
23:24Ploujyeah, repl works
23:25Ploujbut
23:25Ploujwhen I just start it, it says:
23:25PloujLisp connection closed unexpectedly: connection broken by remote peer
23:25Ploujalthough I still see process java running and REPL works
23:26tomojhuh?
23:26Ploujhttp://fpaste.org/Ir4M/
23:26tomojgo to the repl and ,sayoonara
23:26tomojthen start it again
23:26tomojif that doesn't work I dunno what is going on
23:26Plouj, doesn't do anything
23:26clojurebotjava.lang.Exception: Unable to resolve symbol: doesn in this context
23:26PloujI just end up typing in the whole ",sayoonara" string
23:27tomojuhh
23:27Ploujuser=> user=> ,sayoonara
23:27tomojthe repl you're in, what's it called and what mode is it
23:27Ploujjava.lang.Exception: Unable to resolve symbol: sayoonara in this context (NO_SOURCE_FILE:0)
23:27Ploujuser=>
23:27tomoj*inferior-lisp buffer* or something?
23:27Plouj-UUU:**--F1 *inferior-lisp* All L15 (Comint:run)---
23:27tomojyeah, that's wrong
23:27Ploujthat's what M-x slime opens
23:27rhudsonmanuel_: There's a Clojure web framework Compojure -- haven't used it myself but it seems well thought of
23:28tomojM-x slime should open an inferior lisp buffer, but when it's done loading it should put you into a *slime-repl clojure* buffer
23:28tomojif not, something's wrong, I guess
23:29PloujI suspect something is wrong
23:29remleduffslyphon: When you were looking for deftype documentation did you see http://clojure.org/datatypes and http://clojure.org/protocols ?
23:29Ploujthe only other slime buffer I have is *slime-events*
23:29slyphonremleduff: yeah, i found my way over there
23:29slyphonremleduff: thanks :)
23:30tomojmaybe you need to restart emacs? :/ I dunno
23:30tomojM-x slime works fine here with no extra configuration, just the elpa packages
23:31PloujI've tried restarting emacs multiple times :(
23:31Ploujok...
23:31Ploujnow it works...
23:32Ploujand now it doesn't
23:32Ploujit seems to run when I first run package-list-package
23:32Ploujs
23:33Ploujactually no, even then sometimes it looses the connection
23:33tomojI just tried on a brand new emacs23-nox and it seems to work fine, no restarting emacs necesssary
23:33remleduffPlouj; Does M-x clojure-enable-slime-on-existing-buffers work?
23:35Ploujremleduff: well no because it's not connected to slime
23:37tomojjust confirming.. you installed clojure-mode and swank-clojure from package-list-packages, right?
23:38Ploujtomoj: yup, I even double checked that
23:39tomojgot no advice then, I just did the exact same thing from scratch and no problems, good luck
23:39Ploujhttp://fpaste.org/okox/
23:44Ploujtomoj: did you put anything into your ~/.emacs for slime?
23:45remleduffWhat's the value of your slime-lisp-implementations?
23:47tomojnope
23:47tomojdidn't do anything except the package.el installation and clojure-mode, swank-clojure from elpa
23:47tomojthen M-x slime started up fine and C-x C-f foo.clj was in slime mode and connected properly
23:48Ploujremleduff: how do I check that? :)
23:49remleduffI'm not sure the "proper" way, I do C-h v, then type it in
23:49Plouj((clojure ("java" "-classpath" "/home/plouj/.swank-clojure/clojure-1.1.0-master-20091202.150145-1.jar:/home/plouj/.swank-clojure/clojure-contrib-1.1.0-master-20091212\
23:49Plouj.205045-1.jar:/home/plouj/.swank-clojure/swank-clojure-1.1.0.jar" "clojure.main" "--repl") :init swank-clojure-init))
23:50PloujI suspect I need something like (setup-slime)
23:50Ploujbecause if I re-download the clojure-mode and swank-clojure with package-list-packages and then M-x slime, everything works perfectly
23:50tomojdo you use .emacs or .emacs.d/init.el?
23:51tomojI think the package.el installation might dump stuff into .emacs no matter what
23:51tomojbut if that code weren't being loaded, slime wouldn't work at all, I'd expect
23:52PloujI don't have .emacs.d/init.el, so that means ~/.emacs
23:52Ploujanyways, I'll look into this tomorrow
23:52Ploujthanks for helping
23:52Ploujhappy clojuring(?)