#clojure logs

2008-07-10

06:26StartsWithKhi
06:27StartsWithKhow can i get metadata associated with a function?
06:33hoeckStartsWithK: hi
06:33hoeckStartsWithK: only symbols and collections support metadata
06:34StartsWithKif i type ^#'println i get metadata of println function or println symbol then?
06:35StartsWithKi woule like to do something like, (defn get-meta [f] (meta (var f)))
06:36StartsWithKbut it dosn't work
06:49hoeckwith (var f) you are accessing the metadata of a var named "f"
06:50hoeckvar is a special form, evaluated at compile-time
06:50StartsWithKi know, that is my problem, o would like to say (get-meta printf)
06:52hoeck(get-meta (var printf)) ?
06:53StartsWithKthat works
06:53StartsWithKso i can use #' shortcut
06:54hoeckbut then you just renamed meta to get-meta
06:54StartsWithKbut is there any way to remove it completely
06:55StartsWithKits just a minimal example
06:55StartsWithKit would be used more like
06:55hoecki guess no, i think clojure does a statical lookup of vars
06:55StartsWithK(defn user [username] (println (str "Homepage of " username")))
06:56StartsWithK(def views ["/user/<str:username>" user])
06:56StartsWithKand then i can extract needed parts from request url, find names of arguments for user function and send them in that order
07:03StartsWithKok, i can live with #' prefix
07:03StartsWithKany one tried clojure with osgi?
07:05hoeckhow do you use metadata for that (just curious)?
07:05hoecki mean your former example
07:05StartsWithKthere is arglists metadata associated with each function
07:06hoeckahh, i see
07:06StartsWithKso i take (first) from that, turn names of arguments to strings and from map that hold exctracted parts of url i construct list that i use for (apply view args)
09:30mac_hello
09:31mac_I'm having a little problem with how to store a return value from a different thread...
09:33mac_I want something like a java future but more clojurey, is there a good techniqe for such a thing? I tried doing (let [r (ref nil)] (do-work (dosync (ref-set r (something))) r)) but r seems to retain it's original value?
09:33mac_do-work here does the next expression in a specific thread
09:36mac_hmm maybe I'm just checking it too fast? could be that it's not set yet..
09:38mac_hehe yeah that was it. Sorry to bother anyone with my stupidity :D just needed a little wait loop like the Future.get method to wait for it to complete ;)
09:43Chousermac_: if you use an agent and (send), then you can use (await) in your main thread to collect the results.
09:43Chouseror rather, to wait until the results are ready.
09:45Chouser(let [r (agent nil)] (send r (fn [r2] (dowork) "newvalue")) (await r) (prn @r))
09:45mac_Yeah I know, what I did here is a bit re-inventing stuff but I have to please the java libs I'm using. Guess I could restructure things a bit but this works at least..
09:45Chousernote that the function you send to agent r has to return the value instead of setting a ref.
09:45mac_Oh you mean instead of the ref
09:46Chouseryeah.
09:46mac_Yeah that's a bit more idiomatic I suppose. Gonna try that
09:46ChouserI guess if you already have another thread and a communication mechanism you want to use, what you had might be necessary.
09:47mac_Yeah now I'm confusing myself. Of course that's why I had it the way it was hehe
09:47mac_I have a rendering thread that's always the same, like swing (except this is OpenGL) and I have to use that for loading images
09:48mac_But in that case, you think what I did was fine?
09:50mac_I'm pretty new to all this, got my summer vacation now so I'm trying to learn some clojure by making a small game :)
09:55mac_Chouser: since I have to use a specific thread I guess I'm keeping my solution then, thanks a bunch for the input though
10:15Chouseryep, if you need to have the task done in a particular thread, I don't think agents are going to help you at all. Carry on. :-)
10:28cemerickis there any circumstance in which loop *doesn't* bind sequentially?
10:29cemerickor, I should say, any circumstance where it's not supposed to bind sequentially?
10:36ChouserWhen you use recur, the values are bound in parallel. Is that what you're asking?
10:38cemerickChouser: No...I've got a loop form that won't compile, indicating that one of the previously-bound symbols is unavailable in that context. Something like (loop [x (foo) y (bar) z (baz x y)] ...), and it's complaining about the usage of x and y as arguments to baz.
10:38cemerickI've not been able to replicate it in a simple case, though.
10:39Chouserbaz isn't a macro or something, is it? ought to still work, though.
10:39cemerickNope, baz is a very simple helper fn.
10:40Chouserhow big is your non-simple case? :-) pastable?
10:41cemerickChouser: I'll see if I can whittle it down, and rip out some of the irrelevant details.
10:46lisppaste8cemerick pasted "loop not binding sequentially" at http://paste.lisp.org/display/63499
10:46cemerickIf you remove the last binding in the loop (the list destructuring, then foo compiles OK.
10:48Chousernice
10:49cemerickI always feel like I'm doing something wrong if I start thinking I'm hitting a compiler bug, but I think this is a legit example. Someone please smack some sense into me before I post it to the google group. :-)
10:49ChouserI've looked at the destructuring code before, so let me poke at it a little.
10:50Chousermacroexpand on your loop is looking ... odd
10:52ChouserI'm pretty sure you've found a bug in the loop macro
10:54lisppaste8cemerick annotated #63499 with "much-simplified example" at http://paste.lisp.org/display/63499#1
10:55Chouser(loop [x 1 y x [a b] (foo)]) vs. (loop [x 1 y x])
10:55cemerickah, the x's gensym isn't being used
10:56Chouserthere's a big "if" in the loop macro, to try to detect if it needs to destructure or not. there's bug in there somewhere.
10:56Chouserbbl.
11:32cemerickChouser: I see what the problem is, and I've got a *very* partial fix, but I don't know what the best way is to bring it all the way.
12:53Chousercemerick: I'm back. care to share?
13:01Chouserthis is really pretty tricky
13:01Chouser(loop [[a b] [1 2] c a]) ought to work
13:04cemerickChouser: Yes, it really does need to work. Pasting now.
13:05lisppaste8cemerick pasted "barely-helpful loop patch" at http://paste.lisp.org/display/63506
13:07cemerickThe problem is that loop needs to retain the same "signature" as its literal bindings dictate, so it needs to rewrite destructuring(s) into a nested let. In the process, it gensyms binding names, but doesn't propagate those gensyms down into nested forms.
13:07Chouseryep. good summary.
13:08Chouserbut with the example I just gave, Im
13:08ChouserI'm not even sure it's possible to solve using this approach.
13:08cemerickThe "patch" I just pasted makes this work: (loop [x nil [y z] x] nil), but it doesn't help with (loop [x nil z (nil? x) [a b] x] nil), because the gensym for x doesn't get dropped into the (nil?) form.
13:09cemerickI think loop needs to walk all of the value forms, and replace any symbols it finds with gensyms as defined as top-level bindings.
13:09Chouserand we don't really want a code-walker to go through all the value expressions looking for names to replace.
13:09Chouserheh
13:09cemerickThat gets super-tricky though.
13:10Chouserwhat if we wrap each value expression in a let that defines all the names given up to that point?
13:10cemerickThere's really no other way to do it, short of changing how loop binding work (I think). However, getting that right without squashing rebindings in those nested forms would be a serious pain.
13:11Chouseractually, I think my idea might work. Here I'll just whip up a new macro. Give me 4 or 5 hours...
13:11cemerickwhew. yeah, that might do it.
13:11cemerickI'm in there now, I can take a whack.
13:12ChouserI should just let you. I have things I Ought to be doing.
13:12Chouserbut they're not as fun :-/
13:13cemerickHrm, I don't know if this is fun, either. ;-) I'm not nearly 133t enough to be messing with stuff like this.
13:18Chouserlet-destructuring in the loop's value expressions will only happen for the initial values. recur calls will fail, won't they?
13:19Chouseroh, nm -- we'll still need an inner let to do the destructuring for the body of the loop. That will take care of recur calls.
13:20ChouserThe penalty here will be for initial values the destructuring may happen multiple times.
13:20cemerickChouser: That's not my understanding...
13:20cemerickYeah. Not much of a penalty, but yeah.
13:21Chousera small runtime cost that hopefully HotSpot can remove when its not needed.
13:21cemerickActually, no, if this is done right, there won't be any unnecessary destructuring.
13:21Chouserhm
13:21cemerickThe nested lets should just pull in the full collections that have been gensymed (?)
13:22cemerickWe're just aligning symbols, not setting up destructuring.
13:26ChouserI think (loop [[a b] [1 2] c a]) should become:
13:26Chouser(loop* [G__1936 [1 2] G__1937 (clojure/let [[a b] G__1936] a)] (clojure/let [[a b] G__1936 c G__1937]))
13:32ChouserIs there a function that does (subsets '[a b c d]) => [[a] [a b] [a b c] [a b c d]]
13:50lisppaste8Chouser annotated #63506 with "another loop-fix attempt" at http://paste.lisp.org/display/63506#1
13:50Chousercemerick: I think that'll work. not very well tested yet.
13:56cemerickChouser: Yes, I'm pretty sure that will work.
13:56cemerickI was spending a lot of time, and almost have my version completed, but yours is much more concise.
13:59ChouserI really should have let you do it. Sorry I couldn't resist.
14:00cemerickChouser: feh, what do I care? Your solution is cleaner anyway. :-)
14:00Chouserbut see what I mean about the extra destructuring?
14:01Chouser(loop-ch1 [[a b] [1 2] c a d a]) generates (let [[a b] ...] ...) three times, all of which will be run the first time into the loop
14:03cemerickah, yes, I see it now.
14:04cemerickChouser: If the value to be destructured is side-effecting, that could be more than a performance problem.
14:04Chouserhm...
14:05Chouserno, the value parts aren't repeated -- they always use a gensym bound ealier in the loop.
14:05Chouserit's only the destructuring itself (vector accesses, hash lookup, etc.) that are repeated.
14:06ChouserI think. :-)
14:06cemerickYeah. See, I told you I was out of my depth. :-P
14:07cemerickChouser: by all means post that to the group. Hopefully Rich can test and merge it in semi-soon.
14:17Chouserdone
14:18Chousersubsets is a bad name for that function, but I haven't thought of anything better.
15:01JamesIrypowerset http://en.wikipedia.org/wiki/Power_set
15:04Chouserwell, that's not what it does though. From [1 2 3] I want [1] [1 2] and [1 2 3], but not [2 3] or [3].
15:05Chouserit's more like "growing sets" or something. I kinda thought haskell had a builtin function for that, but I don't know Haskell well enough to even know how to look it up.
15:06Chouserwell, google to the rescue. Haskell calls it "inits"
15:08JamesIryChouser: ah, I misunderstood
15:09JamesIrytechnically I think Haskell's inits would return [[][1][1 2][1 2 3]]
15:11NafaiJamesIry: Correct
15:11NafaiPrelude Data.List> inits [1, 2, 3]
15:11Nafai[[],[1],[1,2],[1,2,3]]
15:12erochesterChouser: would this do what you want? (reverse (take (count [1 2 3]) (iterate pop [1 2 3])))
15:13JamesIryNafai, Chouser, I think Haskell's inits makes more sense because it's a total function - any sequence is a valid input. Chouser's variation would be undefined for empty sequences
15:15NafaiRight, haskell's inits just returns a list of an empty list with an empty list argument
15:20Chousermy use case might actually work better with haskell's version
15:20Chousererochester: nice! here's what I've got at the moment:
15:21Chouser(defn subsets [s] (reduce #(conj %1 (conj (or (last %1) []) %2)) [] s))
15:24Chousererochester: iterate pop is genius. I was looking for a way to use iterate, but didn't think of that.
15:24erochestercool. yours actually seems more straightforward in some ways. more complicated in others.
15:25erochesteri'd be interested in knowing if you find a better way to limit the output of iterate. the way i did it seemed messy.
15:27Chouser(take-while seq (iterate pop [1 2 3]))
15:27Chouserbut that makes it harder to go one-more to get inits-like behavior
15:28erochesterexcellent. that's much better (although you're right about going one further.)
15:29erochesteralthough what i posted won't work for inits-like behavior either. it raises an exception when you try to do (pop [])
15:29Chouserhuh. none of these are lazy, and iterate pop doesn't do what we want when passed a list.
15:31erochesterno. that's true too. hmm. what you posted might be your best option.
15:34Chousernaw, it ought to be lazy.
15:34JamesIryLazy would be best - then you could handle infinite sequences
15:37JamesIryI can't help but think something based on map would work
15:38JamesIryEach element of the input sequence would get mapped to a sequence that ended with that element
15:41Chouser(take 10 (map take (iterate inc 0) (repeat [1 2 3])))
15:42Chouserbut you can't count your seq without killing the laziness.
15:49lisppaste8erochester pasted "subsets with lazy-cons" at http://paste.lisp.org/display/63514
15:49erochesterThis won't win any points for being short or elegant, but I think this works for both vectors and lists, it includes [] (for inits behavior), and it's lazy. And it's ugly.
15:49erochesterAnd did I mention, it's ugly?
15:50Chouserit does get the job done.
15:51Chouserby using conj, each "inner" seq is a non-lazy vector. But that's probably fine since you had to calculate all the elements up the the one you're conjing already anyway.
15:52erochesterI love how easy Clojure makes lazy sequences. I'd gotten used to that with Python, and then every time I went back to common lisp, I was banging my head against my desk.
15:52erochesterYou're right. Both about conj and about the assumption I was making that this would be all right.
15:52Chouserpython does lazy sequences? I missed that somehow.
15:53erochesteriterators/generators
15:53Chouseroh, right.
15:57NafaiLazy sequences are really handy
16:01lisppaste8Chouser annotated #63514 with "fully-lazy inits" at http://paste.lisp.org/display/63514#1
16:01Chouserhaving to use lazy-cat is annoying.
16:01Chouserand that might be even less efficient -- I don't know if it uses the same s every time, or if it will re-calculate things.
16:03Chouserok, it does not recalculate. so if I could just figure out how to make take-while go one step further and ditch lazy-cat...
16:13lisppaste8Chouser annotated #63514 with "is this any better? (inits)" at http://paste.lisp.org/display/63514#2
16:16erochesterThat seems to do it. But I can't decide which one I prefer.
16:18Chouseryou could replace the map and take-while with a for, :while, and destructuring. ...still don't know if that's any better though.
16:19erochesterYeah. That's probably a question of what you're used to.
16:22Chouserdoubtless if rhickey chooses to include an inits, he will produce yet another implementation, and probably with a better name too. :-)
16:22erochesterlol.
16:26erochesterI think I've come up with about the best I'm going to do. At least until I walk away from the keyboard.
16:26Chouser:-)
23:45ungraspinessexit
23:55jgrantback