2008-07-10
| 06:26 | StartsWithK | hi |
| 06:27 | StartsWithK | how can i get metadata associated with a function? |
| 06:33 | hoeck | StartsWithK: hi |
| 06:33 | hoeck | StartsWithK: only symbols and collections support metadata |
| 06:34 | StartsWithK | if i type ^#'println i get metadata of println function or println symbol then? |
| 06:35 | StartsWithK | i woule like to do something like, (defn get-meta [f] (meta (var f))) |
| 06:36 | StartsWithK | but it dosn't work |
| 06:49 | hoeck | with (var f) you are accessing the metadata of a var named "f" |
| 06:50 | hoeck | var is a special form, evaluated at compile-time |
| 06:50 | StartsWithK | i know, that is my problem, o would like to say (get-meta printf) |
| 06:52 | hoeck | (get-meta (var printf)) ? |
| 06:53 | StartsWithK | that works |
| 06:53 | StartsWithK | so i can use #' shortcut |
| 06:54 | hoeck | but then you just renamed meta to get-meta |
| 06:54 | StartsWithK | but is there any way to remove it completely |
| 06:55 | StartsWithK | its just a minimal example |
| 06:55 | StartsWithK | it would be used more like |
| 06:55 | hoeck | i guess no, i think clojure does a statical lookup of vars |
| 06:55 | StartsWithK | (defn user [username] (println (str "Homepage of " username"))) |
| 06:56 | StartsWithK | (def views ["/user/<str:username>" user]) |
| 06:56 | StartsWithK | and then i can extract needed parts from request url, find names of arguments for user function and send them in that order |
| 07:03 | StartsWithK | ok, i can live with #' prefix |
| 07:03 | StartsWithK | any one tried clojure with osgi? |
| 07:05 | hoeck | how do you use metadata for that (just curious)? |
| 07:05 | hoeck | i mean your former example |
| 07:05 | StartsWithK | there is arglists metadata associated with each function |
| 07:06 | hoeck | ahh, i see |
| 07:06 | StartsWithK | so 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:30 | mac_ | hello |
| 09:31 | mac_ | I'm having a little problem with how to store a return value from a different thread... |
| 09:33 | mac_ | 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:33 | mac_ | do-work here does the next expression in a specific thread |
| 09:36 | mac_ | hmm maybe I'm just checking it too fast? could be that it's not set yet.. |
| 09:38 | mac_ | 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:43 | Chouser | mac_: if you use an agent and (send), then you can use (await) in your main thread to collect the results. |
| 09:43 | Chouser | or rather, to wait until the results are ready. |
| 09:45 | Chouser | (let [r (agent nil)] (send r (fn [r2] (dowork) "newvalue")) (await r) (prn @r)) |
| 09:45 | mac_ | 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:45 | Chouser | note that the function you send to agent r has to return the value instead of setting a ref. |
| 09:45 | mac_ | Oh you mean instead of the ref |
| 09:46 | Chouser | yeah. |
| 09:46 | mac_ | Yeah that's a bit more idiomatic I suppose. Gonna try that |
| 09:46 | Chouser | I guess if you already have another thread and a communication mechanism you want to use, what you had might be necessary. |
| 09:47 | mac_ | Yeah now I'm confusing myself. Of course that's why I had it the way it was hehe |
| 09:47 | mac_ | 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:48 | mac_ | But in that case, you think what I did was fine? |
| 09:50 | mac_ | 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:55 | mac_ | 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:15 | Chouser | yep, 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:28 | cemerick | is there any circumstance in which loop *doesn't* bind sequentially? |
| 10:29 | cemerick | or, I should say, any circumstance where it's not supposed to bind sequentially? |
| 10:36 | Chouser | When you use recur, the values are bound in parallel. Is that what you're asking? |
| 10:38 | cemerick | Chouser: 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:38 | cemerick | I've not been able to replicate it in a simple case, though. |
| 10:39 | Chouser | baz isn't a macro or something, is it? ought to still work, though. |
| 10:39 | cemerick | Nope, baz is a very simple helper fn. |
| 10:40 | Chouser | how big is your non-simple case? :-) pastable? |
| 10:41 | cemerick | Chouser: I'll see if I can whittle it down, and rip out some of the irrelevant details. |
| 10:46 | lisppaste8 | cemerick pasted "loop not binding sequentially" at http://paste.lisp.org/display/63499 |
| 10:46 | cemerick | If you remove the last binding in the loop (the list destructuring, then foo compiles OK. |
| 10:48 | Chouser | nice |
| 10:49 | cemerick | I 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:49 | Chouser | I've looked at the destructuring code before, so let me poke at it a little. |
| 10:50 | Chouser | macroexpand on your loop is looking ... odd |
| 10:52 | Chouser | I'm pretty sure you've found a bug in the loop macro |
| 10:54 | lisppaste8 | cemerick annotated #63499 with "much-simplified example" at http://paste.lisp.org/display/63499#1 |
| 10:55 | Chouser | (loop [x 1 y x [a b] (foo)]) vs. (loop [x 1 y x]) |
| 10:55 | cemerick | ah, the x's gensym isn't being used |
| 10:56 | Chouser | there'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:56 | Chouser | bbl. |
| 11:32 | cemerick | Chouser: 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:53 | Chouser | cemerick: I'm back. care to share? |
| 13:01 | Chouser | this is really pretty tricky |
| 13:01 | Chouser | (loop [[a b] [1 2] c a]) ought to work |
| 13:04 | cemerick | Chouser: Yes, it really does need to work. Pasting now. |
| 13:05 | lisppaste8 | cemerick pasted "barely-helpful loop patch" at http://paste.lisp.org/display/63506 |
| 13:07 | cemerick | The 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:07 | Chouser | yep. good summary. |
| 13:08 | Chouser | but with the example I just gave, Im |
| 13:08 | Chouser | I'm not even sure it's possible to solve using this approach. |
| 13:08 | cemerick | The "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:09 | cemerick | I 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:09 | Chouser | and we don't really want a code-walker to go through all the value expressions looking for names to replace. |
| 13:09 | Chouser | heh |
| 13:09 | cemerick | That gets super-tricky though. |
| 13:10 | Chouser | what if we wrap each value expression in a let that defines all the names given up to that point? |
| 13:10 | cemerick | There'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:11 | Chouser | actually, I think my idea might work. Here I'll just whip up a new macro. Give me 4 or 5 hours... |
| 13:11 | cemerick | whew. yeah, that might do it. |
| 13:11 | cemerick | I'm in there now, I can take a whack. |
| 13:12 | Chouser | I should just let you. I have things I Ought to be doing. |
| 13:12 | Chouser | but they're not as fun :-/ |
| 13:13 | cemerick | Hrm, I don't know if this is fun, either. ;-) I'm not nearly 133t enough to be messing with stuff like this. |
| 13:18 | Chouser | let-destructuring in the loop's value expressions will only happen for the initial values. recur calls will fail, won't they? |
| 13:19 | Chouser | oh, 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:20 | Chouser | The penalty here will be for initial values the destructuring may happen multiple times. |
| 13:20 | cemerick | Chouser: That's not my understanding... |
| 13:20 | cemerick | Yeah. Not much of a penalty, but yeah. |
| 13:21 | Chouser | a small runtime cost that hopefully HotSpot can remove when its not needed. |
| 13:21 | cemerick | Actually, no, if this is done right, there won't be any unnecessary destructuring. |
| 13:21 | Chouser | hm |
| 13:21 | cemerick | The nested lets should just pull in the full collections that have been gensymed (?) |
| 13:22 | cemerick | We're just aligning symbols, not setting up destructuring. |
| 13:26 | Chouser | I think (loop [[a b] [1 2] c a]) should become: |
| 13:26 | Chouser | (loop* [G__1936 [1 2] G__1937 (clojure/let [[a b] G__1936] a)] (clojure/let [[a b] G__1936 c G__1937])) |
| 13:32 | Chouser | Is there a function that does (subsets '[a b c d]) => [[a] [a b] [a b c] [a b c d]] |
| 13:50 | lisppaste8 | Chouser annotated #63506 with "another loop-fix attempt" at http://paste.lisp.org/display/63506#1 |
| 13:50 | Chouser | cemerick: I think that'll work. not very well tested yet. |
| 13:56 | cemerick | Chouser: Yes, I'm pretty sure that will work. |
| 13:56 | cemerick | I was spending a lot of time, and almost have my version completed, but yours is much more concise. |
| 13:59 | Chouser | I really should have let you do it. Sorry I couldn't resist. |
| 14:00 | cemerick | Chouser: feh, what do I care? Your solution is cleaner anyway. :-) |
| 14:00 | Chouser | but see what I mean about the extra destructuring? |
| 14:01 | Chouser | (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:03 | cemerick | ah, yes, I see it now. |
| 14:04 | cemerick | Chouser: If the value to be destructured is side-effecting, that could be more than a performance problem. |
| 14:04 | Chouser | hm... |
| 14:05 | Chouser | no, the value parts aren't repeated -- they always use a gensym bound ealier in the loop. |
| 14:05 | Chouser | it's only the destructuring itself (vector accesses, hash lookup, etc.) that are repeated. |
| 14:06 | Chouser | I think. :-) |
| 14:06 | cemerick | Yeah. See, I told you I was out of my depth. :-P |
| 14:07 | cemerick | Chouser: by all means post that to the group. Hopefully Rich can test and merge it in semi-soon. |
| 14:17 | Chouser | done |
| 14:18 | Chouser | subsets is a bad name for that function, but I haven't thought of anything better. |
| 15:01 | JamesIry | powerset http://en.wikipedia.org/wiki/Power_set |
| 15:04 | Chouser | well, 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:05 | Chouser | it'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:06 | Chouser | well, google to the rescue. Haskell calls it "inits" |
| 15:08 | JamesIry | Chouser: ah, I misunderstood |
| 15:09 | JamesIry | technically I think Haskell's inits would return [[][1][1 2][1 2 3]] |
| 15:11 | Nafai | JamesIry: Correct |
| 15:11 | Nafai | Prelude Data.List> inits [1, 2, 3] |
| 15:11 | Nafai | [[],[1],[1,2],[1,2,3]] |
| 15:12 | erochester | Chouser: would this do what you want? (reverse (take (count [1 2 3]) (iterate pop [1 2 3]))) |
| 15:13 | JamesIry | Nafai, 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:15 | Nafai | Right, haskell's inits just returns a list of an empty list with an empty list argument |
| 15:20 | Chouser | my use case might actually work better with haskell's version |
| 15:20 | Chouser | erochester: nice! here's what I've got at the moment: |
| 15:21 | Chouser | (defn subsets [s] (reduce #(conj %1 (conj (or (last %1) []) %2)) [] s)) |
| 15:24 | Chouser | erochester: iterate pop is genius. I was looking for a way to use iterate, but didn't think of that. |
| 15:24 | erochester | cool. yours actually seems more straightforward in some ways. more complicated in others. |
| 15:25 | erochester | i'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:27 | Chouser | (take-while seq (iterate pop [1 2 3])) |
| 15:27 | Chouser | but that makes it harder to go one-more to get inits-like behavior |
| 15:28 | erochester | excellent. that's much better (although you're right about going one further.) |
| 15:29 | erochester | although what i posted won't work for inits-like behavior either. it raises an exception when you try to do (pop []) |
| 15:29 | Chouser | huh. none of these are lazy, and iterate pop doesn't do what we want when passed a list. |
| 15:31 | erochester | no. that's true too. hmm. what you posted might be your best option. |
| 15:34 | Chouser | naw, it ought to be lazy. |
| 15:34 | JamesIry | Lazy would be best - then you could handle infinite sequences |
| 15:37 | JamesIry | I can't help but think something based on map would work |
| 15:38 | JamesIry | Each element of the input sequence would get mapped to a sequence that ended with that element |
| 15:41 | Chouser | (take 10 (map take (iterate inc 0) (repeat [1 2 3]))) |
| 15:42 | Chouser | but you can't count your seq without killing the laziness. |
| 15:49 | lisppaste8 | erochester pasted "subsets with lazy-cons" at http://paste.lisp.org/display/63514 |
| 15:49 | erochester | This 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:49 | erochester | And did I mention, it's ugly? |
| 15:50 | Chouser | it does get the job done. |
| 15:51 | Chouser | by 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:52 | erochester | I 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:52 | erochester | You're right. Both about conj and about the assumption I was making that this would be all right. |
| 15:52 | Chouser | python does lazy sequences? I missed that somehow. |
| 15:53 | erochester | iterators/generators |
| 15:53 | Chouser | oh, right. |
| 15:57 | Nafai | Lazy sequences are really handy |
| 16:01 | lisppaste8 | Chouser annotated #63514 with "fully-lazy inits" at http://paste.lisp.org/display/63514#1 |
| 16:01 | Chouser | having to use lazy-cat is annoying. |
| 16:01 | Chouser | and 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:03 | Chouser | ok, 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:13 | lisppaste8 | Chouser annotated #63514 with "is this any better? (inits)" at http://paste.lisp.org/display/63514#2 |
| 16:16 | erochester | That seems to do it. But I can't decide which one I prefer. |
| 16:18 | Chouser | you could replace the map and take-while with a for, :while, and destructuring. ...still don't know if that's any better though. |
| 16:19 | erochester | Yeah. That's probably a question of what you're used to. |
| 16:22 | Chouser | doubtless if rhickey chooses to include an inits, he will produce yet another implementation, and probably with a better name too. :-) |
| 16:22 | erochester | lol. |
| 16:26 | erochester | I think I've come up with about the best I'm going to do. At least until I walk away from the keyboard. |
| 16:26 | Chouser | :-) |
| 23:45 | ungraspiness | exit |
| 23:55 | jgrant | back |